
    
        
        
        
                
        
        
        
                
        
        
        
                
        
        
        
                
    
        
        
                
        
        
        
            
{"version":"https:\/\/jsonfeed.org\/version\/1","title":"mathspp.com feed","home_page_url":"https:\/\/mathspp.com\/blog\/tags\/fractals","feed_url":"https:\/\/mathspp.com\/blog\/tags\/fractals.json","description":"Stay up-to-date with the articles on mathematics and programming that get published to mathspp.com.","author":{"name":"Rodrigo Gir\u00e3o Serr\u00e3o"},"items":[{"title":"Animating a tree fractal","date_published":"2025-01-12T19:10:00+01:00","id":"https:\/\/mathspp.com\/blog\/animating-a-tree-fractal","url":"https:\/\/mathspp.com\/blog\/animating-a-tree-fractal","content_html":"<p>This article walks through the code used to animate a tree fractal.<\/p>\n\n<p>I really enjoy fractals and for the longest time I've been meaning to draw the classical tree fractal that starts with the main trunk which then successively splits into two branches, that themselves can be seen as the full tree.<\/p>\n<p>Today I quickly put together the code to do this and then I animated the rotation of the tree to make sure it's easy to see the self-similarity of the tree.<\/p>\n<p>This is the animated GIF that I produced:<\/p>\n<p><img alt=\"Animated GIF of a tree fractal rotating and zooming in, so that the end position is the same as the starting position, displaying the self-similarity properties of the fractal.\" src=\"\/user\/pages\/02.blog\/animating-a-tree-fractal\/_tree.gif?decoding=auto&amp;fetchpriority=auto\"><\/p>\n<h2 id=\"drawing-the-tree\">Drawing the tree<a href=\"#drawing-the-tree\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>To draw the tree I wrote a recursive function (obviously!) that draws a trunk and then recursively draws the remainder of the tree.\nTo &ldquo;recursively draw the remainder of the tree&rdquo; I needed to compute the two trunks that stem from the trunk I just drew, so to do that I:<\/p>\n<ul><li>computed the direction of the trunk I just drew as a numpy vector;<\/li>\n<li>rotated this vector by 60 degrees (clockwise and counter-clockwise);<\/li>\n<li>scaled down this vector; and<\/li>\n<li>used it to compute the two new trunks.<\/li>\n<\/ul><p>The recursive function looks like this:<\/p>\n<pre><code class=\"language-py\">def tree(screen, start, to, depth=0):\n    if depth &gt;= 15:\n        return\n    sx, sy = start\n    tx, ty = to\n    pygame.draw.line(\n        screen,\n        BLACK,\n        (WIDTH \/\/ 2 + sx, HEIGHT \/\/ 2 - sy),\n        (WIDTH \/\/ 2 + tx, HEIGHT \/\/ 2 - ty),\n        1,\n    )\n    direction = np.array([[tx - sx], [ty - sy]])\n    for angle in [pi \/ 3, -pi \/ 3]:\n        rot = np.array(\n            [\n                [cos(angle), -sin(angle)],\n                [sin(angle), cos(angle)],\n            ]\n        )\n        new_direction = ((rot @ ((direction) \/ 1.7))).reshape((2,))\n        tree(screen, to, to + new_direction, depth + 1)<\/code><\/pre>\n<p>One important thing that I ended up doing, and that explains the weird calculations inside the call to <code>pygame.draw.line<\/code>, is that I decided to do all calculations as if the coordinate system were the standard one from maths class: the origin is at the centre of the pygame window and the values of the coordinate y increase by going up, not by going down.\nThen, I need to convert from this sytem to the pygame system right before drawing, which is why I add <code>(WIDTH \/\/ 2, HEIGHT \/\/ 2)<\/code> to the points we're drawing and then for the y coordinate I need to use the symmetric value (<code>-y<\/code> instead of <code>y<\/code>) to compensate for the fact that the y axis is flipped.<\/p>\n<p>The full script to draw the tree looks like this:<\/p>\n<pre><code class=\"language-py\">from math import sin, cos, pi\nimport sys\n\nimport numpy as np\nimport pygame\nimport pygame.locals\n\nWIDTH, HEIGHT = 600, 400\n\nWHITE = (255, 255, 255)\nBLACK = (0, 0, 0)\n\nscreen = pygame.display.set_mode((WIDTH, HEIGHT))\n\ndef tree(screen, start, to, depth=0):\n    ...\n\ndef main() -&gt; None:\n    screen.fill(WHITE)\n    tree(screen, np.array((0, -200)), np.array((0, 0)))\n    pygame.display.flip()\n    pygame.image.save(screen, \"tree.png\")\n\n    while True:\n        for event in pygame.event.get():\n            if event.type == pygame.locals.QUIT:\n                pygame.quit()\n                sys.exit(0)\n\nif __name__ == \"__main__\":\n    main()<\/code><\/pre>\n<h2 id=\"animating-the-tree\">Animating the tree<a href=\"#animating-the-tree\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>To make it easier to animate the tree I first started by splitting the function <code>tree<\/code> in two:<\/p>\n<ol><li>a...<\/li><\/ol>","summary":"This article walks through the code used to animate a tree fractal.","date_modified":"2025-07-23T16:49:02+02:00","tags":["fractals","mathematics","programming","pygame","python","recursion","visualisation"],"image":"\/user\/pages\/02.blog\/animating-a-tree-fractal\/thumbnail.webp"},{"title":"(More) Animations from first principles","date_published":"2023-09-08T12:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/more-animations-from-first-principles-in-5-minutes","url":"https:\/\/mathspp.com\/blog\/more-animations-from-first-principles-in-5-minutes","content_html":"<p>Create a zooming animation from first principles in Python. In 5 minutes. Kind of.<\/p>\n\n<video width=\"400\" height=\"400\" poster=\"\/blog\/more-animations-from-first-principles-in-5-minutes\/_zoom_triangle.mp4.thumb.png\" controls><source src=\"\/blog\/more-animations-from-first-principles-in-5-minutes\/_zoom_triangle.mp4\" type=\"video\/mp4\">\n  You can't watch the video animation of a recursive triangular structure, zooming in and rotating, animated with a Python and pygame script.\n<\/source><\/video><p>This is a follow-up to my recent article called <a href=\"\/blog\/animations-from-first-principles-in-5-minutes\">&ldquo;Animations from first principles (in 5 minutes)&rdquo;<\/a>.\nIn that article, we created a simple animation with Python and pygame.<\/p>\n<p>In <em>this<\/em> article, we will create a different type of animation, where we will draw a recursive triangular structure that can be zoomed in indefinitely.\nWe'll be using Python and <code>pygame<\/code>, so make sure you install it in your preferred way, and make sure it was installed properly:<\/p>\n<pre><code class=\"language-pycon\">&gt;&gt;&gt; import pygame\npygame 2.5.1 (SDL 2.28.2, Python 3.11.4)\nHello from the pygame community. https:\/\/www.pygame.org\/contribute.html<\/code><\/pre>\n<p>The code in this article was written with Python 3.11 and <code>pygame<\/code> 2.5.1.\nHowever, it should run well on older versions of Python\/<code>pygame<\/code> because we're only using fundamental features that have been around for a while and that are unlikely to go anywhere.<\/p>\n<h2 id=\"in-5-minutes\">In 5 minutes?<a href=\"#in-5-minutes\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>I have no idea if you can go through this in 5 minutes.\nYou'll likely need more time if these ideas are new to you and you're typing the code yourself.\nHowever, I did present most of this material in 5 minutes in <a href=\"\/talks\">a lightning talk at PyCon Portugal<\/a>.<\/p>\n<h2 id=\"i-ll-cheat-a-bit\">I'll cheat a bit<a href=\"#i-ll-cheat-a-bit\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>For this demo, I'll cheat a bit and I will add a little bit of boilerplate for free.\nThis is a class <code>Point<\/code> that I'm using to represent 2D points.\nThe idea is to make it easier to add and subtract points, and to multiply and divide points by numbers.<\/p>\n<p>The class <code>Point<\/code> looks like this:<\/p>\n<pre><code class=\"language-py\">class Point:\n    def __init__(self, x, y):\n        self.values = (x, y)\n\n    def __add__(self, other):\n        x, y = self.values\n        x_, y_ = other.values\n        return Point(x + x_, y + y_)\n\n    def __sub__(self, other):\n        x, y = self.values\n        x_, y_ = other.values\n        return Point(x - x_, y - y_)\n\n    def __mul__(self, other):\n        return Point(self.values[0] * other, self.values[1] * other)\n\n    __rmul__ = __mul__\n\n    def __truediv__(self, other):\n        return Point(self.values[0] \/ other, self.values[1] \/ other)\n\n    @property\n    def length(self):\n        return self.values[0] ** 2 + self.values[1] ** 2<\/code><\/pre>\n<p>It uses <a href=\"\/blog\/pydonts\/overloading-arithmetic-operators-with-dunder-methods\">arithmetic dunder methods<\/a> and a <a href=\"\/blog\/pydonts\/properties\">property<\/a>, but it is just so I can do operations like <code>Point(1, 2) + Point(3, 4)<\/code> or <code>3 * Point(1, 0)<\/code>.<\/p>\n<p>With this out of the way, let us start!<\/p>\n<h2 id=\"creating-the-canvas-to-draw-on\">Creating the canvas to draw on<a href=\"#creating-the-canvas-to-draw-on\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>Just like last time, we'll start by making sure we can get a black screen in front of us:<\/p>\n<pre><code class=\"language-py\">import pygame\n\nWHITE = (255, 255, 255)\nBLACK = (0, 0, 0)\n\nscreen = pygame.display.set_mode((400, 400))\nscreen.fill(BLACK)\n\nwhile True:\n    pygame.display.flip()<\/code><\/pre>\n<p>The code above fills a 400 by 400 screen with black and then it refreshes it forever.\nIf you run this program, you'll see a black screen:<\/p>\n<figure class=\"image-caption\"><img title=\"A black screen.\" alt=\"\" src=\"\/user\/pages\/02.blog\/more-animations-from-first-principles-in-5-minutes\/_black_screen.webp\"><figcaption class=\"\">A black screen.<\/figcaption><\/figure><p>To close this window, you'll need to interrupt <em>the Python shell where you ran your program<\/em>.<\/p>\n<h2 id=\"drawing-a-triangle\">Drawing a triangle<\/h2>...","summary":"Create a zooming animation from first principles in Python. In 5 minutes. Kind of.","date_modified":"2025-07-23T16:49:02+02:00","tags":["fractals","geometry","mathematics","programming","pygame","python","recursion","visualisation"],"image":"\/user\/pages\/02.blog\/more-animations-from-first-principles-in-5-minutes\/thumbnail.webp"},{"title":"Buffet of self-references","date_published":"2021-06-06T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/buffet-of-self-references","url":"https:\/\/mathspp.com\/blog\/buffet-of-self-references","content_html":"<p>This article will twist and bend your mind a little bit,\nas we go over some interesting self-referential concepts and objects.<\/p>\n\n<p><img alt=\"\" src=\"\/images\/c\/c\/9\/0\/5\/cc9058d44cf9090fb31e10ac154a2942eebdfac6-thumbnail.webp\"><\/p>\n<h2 id=\"introduction\">Introduction<a href=\"#introduction\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>This article was brought to life by all of the readers that\n<a href=\"https:\/\/github.com\/sponsors\/rodrigogiraoserrao\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">sponsored my work<\/a>.\nas we reached the goal that was set for the page.\nI said I would write an article about self-referential objects\nwhen the goal was reached, so here we are.<\/p>\n<p>In this article I want to bring a couple of interesting things\nto your attention, hopefully showing you something new.\nHowever, I won't go into too much detail about the things\nI present here.<\/p>\n<h2 id=\"the-impossible-collection\">The impossible collection<a href=\"#the-impossible-collection\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>To kick things off, I'd like to tell you a true story about\nan uncle of mine.\nThis uncle of mine is a very interesting person, and he's the\none who is most responsible for me having pursued an education\nin maths.\nOne day, he walked up to me and started telling me about a\ncollection he wanted to create.\nHe said<\/p>\n<blockquote>\n<p>&ndash; I want to create a really nice collection of objects.\nI want to collect objects that have nothing to do with\neach other.<\/p>\n<\/blockquote>\n<p>At this point I could already tell I was about to have my mind\nblown, but I let my uncle continue:<\/p>\n<blockquote>\n<p>&ndash; I didn't know exactly where to start, so I figured I\nmight as well just start simple, so I started by adding\na pen to my collection.\nThen, in order to keep building the collection, I had to\nfind an item that had nothing to do with my pen;\nfor example, I could not add a pencil to the collection...\nSo, I ended up finding this peculiar toy that looked like\na penguin, and so I decided to add it to my collection.<\/p>\n<\/blockquote>\n<p>&ldquo;That sounds about right&rdquo; was more or less what I thought.\nI mean, a penguin toy doesn't sound like it would have anything\nin common with a pen, right?\nThen, my uncle proceeded:<\/p>\n<blockquote>\n<p>&ndash; As soon as I added the penguin to the collection,\nI realised the penguin and the pen had something in common.\nAfter all, that's what a collection is: a set of objects\nthat have something in common.\nAnd so, I had to go back to the drawing board...<\/p>\n<\/blockquote>\n<p>Now, this story I told you <em>did<\/em> happen,\nbut I am not 100% sure that the story my uncle told me was true.\nRegardless of that, the point of his story was to get me thinking\nabout all the funny things that happen\nwhen objects reference themselves.<\/p>\n<h2 id=\"brain-twisting-paradoxes\">Brain-twisting paradoxes<a href=\"#brain-twisting-paradoxes\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<h3 id=\"liar-s-paradox\">Liar's paradox<a href=\"#liar-s-paradox\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h3>\n<p>Along the lines of the funny things that happen when self-reference\ncomes into play, let me share a very entertaining paradox with you:<\/p>\n<div class=\"notices blue\">\n<p>The next statement is true.<\/p>\n<\/div>\n<div class=\"notices green\">\n<p>The previous statement is false.<\/p>\n<\/div>\n<p>Now, can you look at the two previous statements and determine\nwhether which one is true or false?<\/p>\n<p>If the first statement is true, then it implies the second statement\nis true (because that is what the first...<\/p>","summary":"This article will twist and bend your mind a little bit, as we go over some interesting self-referential concepts and objects.","date_modified":"2025-07-23T16:49:02+02:00","tags":["fractals","logic","mathematics"],"image":"\/user\/pages\/02.blog\/buffet-of-self-references\/thumbnail.webp"},{"title":"Mathy broccoli","date_published":"2019-04-02T22:50:00+02:00","id":"https:\/\/mathspp.com\/blog\/mathy-broccoli","url":"https:\/\/mathspp.com\/blog\/mathy-broccoli","content_html":"<p>This post shows how fractals occur naturally in broccoli, one of my favourite vegetables.<\/p>\n\n<p>This post is about showing you how mathematics is beautiful and how it occurs naturally in the world around us. In two previous posts (<a href=\"https:\/\/mathspp.com\/blog\/julia-set\">here<\/a> and <a href=\"https:\/\/mathspp.com\/blog\/mandelbrot-set\">here<\/a>), I talked about fractals. Today, I am going to do the same thing \u2014 except now, I will use broccoli as the example instead of some weird set on the complex plane!<\/p>\n<p>Here's an image with two broccoli poorly edited into the image:<\/p>\n<figure class=\"image-caption\"><img title=\"Two broccoli.\" alt=\"An image with two broccoli poorly edited into a white background.\" src=\"\/user\/pages\/02.blog\/mathy-broccoli\/_broccoli.webp\"><figcaption class=\"\">Two broccoli.<\/figcaption><\/figure>\n<p>Which one is bigger? There are only two possible answers:<\/p>\n<ol>\n<li>Exhibit <strong>A<\/strong> is bigger.<\/li>\n<li>Exhibit <strong>B<\/strong> is smaller.<\/li>\n<\/ol>\n<p>Right? <strong>WRONG!<\/strong> <a href=\"https:\/\/www.youtube.com\/watch?v=QVCmWVD-NH4\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Don't be fooled like Joey!<\/a> Options 1 and 2 are the same...<\/p>\n<p>Going back to the matter at hand, which one is bigger? The right answer is exhibit <strong>A<\/strong>, but I don't really expect you to get that. The actual question is: how much bigger is <strong>A<\/strong> compared to <strong>B<\/strong>?<\/p>\n<p>In fact, <strong>B<\/strong> was \"removed\" from inside <strong>A<\/strong>! But they both look like perfectly fine broccoli, right? This is one of the properties of fractals: self-similarity. Fractals usually exhibit this very interesting behavior: you keep zooming in, and the things you see while you zoom in still look like the original one! (For example, in <a href=\"https:\/\/www.youtube.com\/watch?v=pCpLWbHVNhk\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this video<\/a>, we are zooming in on the <a href=\"https:\/\/mathspp.com\/blog\/mandelbrot-set\">Mandelbrot set<\/a>; by second 13, we get the same shape with which we started!)<\/p>\n<p>I'll show you the two pictures again, but this time without the background removed\u2014you can use it to get a relative scale of the two images.<\/p>\n<figure class=\"image-caption\"><img title=\"Same broccoli and the surface background.\" alt=\"The same two broccoli, but this time you can see the texture of the surface they were laid on, showing that taking a picture of broccoli B required zooming in significantly, when compared to broccoli A.\" src=\"\/user\/pages\/02.blog\/mathy-broccoli\/_broccoli_with_background.webp\"><figcaption class=\"\">Same broccoli and the surface background.<\/figcaption><\/figure>\n<p>This self-similarity can also be seen from a recursive point of view, by which I would define <em>broccoli<\/em> this way:<\/p>\n<blockquote>\n<p><em>Broccoli<\/em>: a green vegetable composed of a stalk and smaller broccoli.<\/p>\n<\/blockquote>\n<p>If you take a moment to think about it, this is exactly what is going on! Broccoli is the vegetable that has smaller versions of itself on top of a stalk.<\/p>\n<p>Of course, I went even further, and from within <strong>B<\/strong>, I removed this:<\/p>\n<figure class=\"image-caption\"><img title=\"A tiny piece of broccoli.\" alt=\"A photo of a tiny piece of broccoli.\" src=\"\/user\/pages\/02.blog\/mathy-broccoli\/_tiny_broccoli.webp\"><figcaption class=\"\">A tiny piece of broccoli.<\/figcaption><\/figure>\n<p>At this point, everything is so small that Mother Nature never bothered to finish up the details, so there isn\u2019t much more zooming I could do.<\/p>\n<p>Now let us zoom out. I started out with this:<\/p>\n<figure class=\"image-caption\"><img title=\"An average supermarket broccoli.\" alt=\"A picture of a regular supermarket broccoli.\" src=\"\/user\/pages\/02.blog\/mathy-broccoli\/_big_broccoli.webp\"><figcaption class=\"\">An average supermarket broccoli.<\/figcaption><\/figure>\n<p>Then I extracted exhibit <strong>A<\/strong>, then I got exhibit <strong>B<\/strong> from it, and from it, I got <em>Broccoli Jr. Jr. Jr.<\/em>.<\/p>\n<p>As a final image, I outlined the self-similar pattern of broccoli. Next time you eat broccoli, take the time to appreciate the fractals you are eating!<\/p>\n<figure class=\"image-caption\"><img title=\"Self-similarity in broccoli.\" alt=\"The same broccoli from the side, with successive stems highlighting the self-similarity of broccoli.\" src=\"\/user\/pages\/02.blog\/mathy-broccoli\/_big_broccoli_marked.webp\"><figcaption class=\"\">Self-similarity in broccoli.<\/figcaption><\/figure>","summary":"This post shows how fractals occur naturally in broccoli, one of my favourite vegetables.","date_modified":"2025-07-23T16:49:02+02:00","tags":["fractals","geometry","visualisation","slice of life"],"image":"\/user\/pages\/02.blog\/mathy-broccoli\/thumbnail.webp"},{"title":"Fractals and the filled Julia set","date_published":"2017-10-17T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/julia-set","url":"https:\/\/mathspp.com\/blog\/julia-set","content_html":"<p>The filled Julia set is a really cool fractal that kind of resembles the <a href=\"https:\/\/mathspp.com\/blog\/mandelbrot\">Mandelbrot set<\/a>!<\/p>\n\n<p><img alt=\"A screenshot of a filled Julia set done in Python\" src=\"\/user\/pages\/02.blog\/julia-set\/juliaset2.webp\"><\/p>\n<p>(You may want to read <a href=\"https:\/\/mathspp.com\/blog\/mandelbrot\">my post<\/a> on the Mandelbrot set as it is closely related to this one!)<\/p>\n<p>The Mandelbrot set is just one, and is built in the complex plane. The filled Julia set, on the other hand, is not \"just one set\". There is one filled Julia set for each complex number <span class=\"mathjax mathjax--inline\">\\(z_0 \\in \\mathbb{C}\\)<\/span>. If you pick a complex number <span class=\"mathjax mathjax--inline\">\\(z_0\\)<\/span>, then its filled Julia set is the set of points in the complex plane for which the repeated application of <span class=\"mathjax mathjax--inline\">\\(f(z) = z^2 + z_0\\)<\/span> diverges to infinity. Formally, the filled Julia set associated with <span class=\"mathjax mathjax--inline\">\\(z_0\\)<\/span> is<\/p>\n<p class=\"mathjax mathjax--block\">\\[\n    \\{ z \\in \\mathbb{C}: \\lim_{n \\to \\infty} |f^n(z)| = \\infty \\} \\subset \\mathbb{C}\\]<\/p>\n<p>The screenshot above shows the filled Julia set for some <span class=\"mathjax mathjax--inline\">\\(z_0\\)<\/span> I picked. The points in black belong in the set and the coloured points do not (the colouring was done as explained in the <a href=\"https:\/\/mathspp.com\/blog\/mandelbrot\">article<\/a> about the Mandelbrot set). I took another screenshot, here:<\/p>\n<p><img alt=\"A different filled Julia set done in Python\" src=\"\/images\/0\/a\/5\/6\/2\/0a5629a67e2d3951c2a891a0deeb2722b1604f7f-juliaset.webp\"><\/p>\n<p>from a <a href=\"https:\/\/github.com\/rodrigogiraoserrao\/fractals\/blob\/master\/juliaSet.py\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">small Python 3 program<\/a> I wrote with pygame. You press any point in the complex plane and the program builds its corresponding filled Julia set. You can use the left and right arrows to navigate the sets you already created. Pressing the space bar cleans the fractal you are viewing. You can also download a Windows executable from <a href=\"https:\/\/github.com\/rodrigogiraoserrao\/fractals\/blob\/master\/juliaSet.rar\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">here<\/a>.<\/p>","date_modified":"2024-08-13T12:47:46+02:00","tags":["mathematics","programming","python","fractals","visualisation","pygame"],"image":"\/user\/pages\/02.blog\/julia-set\/juliaset.webp"},{"title":"Fractals and the Mandelbrot set","date_published":"2017-10-13T00:00:00+02:00","id":"https:\/\/mathspp.com\/blog\/mandelbrot-set","url":"https:\/\/mathspp.com\/blog\/mandelbrot-set","content_html":"<p>I have always liked the concept of fractal. They are very beautiful, they have a notion of infinity embedded in them, and they make no sense (seriously though, <em>self-similarity<\/em>?). How could they not be loved?<\/p>\n\n<p><img src=\"\/blog\/mandelbrot-set\/.\/thumbnail.webp\" alt=\"A rendering of the Mandelbrot set\"><\/p>\n<p>Despite being fond of fractals, I had never understood them because I didn't know how to mathematically define one.\nI knew how to draw some, for example the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Koch_snowflake\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">snowflake<\/a> or the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Sierpinski_triangle\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Sierpinski triangle<\/a>, but drawing a fractal and mathematically defining it aren't quite the same thing...<\/p>\n<p>Enlightenment struck after watching <a href=\"https:\/\/www.youtube.com\/watch?v=NGMRB4O922I\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">this<\/a> video from Numberphile about the Mandelbrot set, the fractal I presented above.\nAfter all, a fractal like this was not but a simple formula and a check for a bound on a sequence!\nI recommend to all of you that you watch that video.<\/p>\n<p>To decide if a complex number <span class=\"mathjax mathjax--inline\">\\(c\\)<\/span> belongs to the fractal or not, you define <span class=\"mathjax mathjax--inline\">\\(f(x) = x^2 + c\\)<\/span> and then you look at the sequence <span class=\"mathjax mathjax--inline\">\\(c, f(c), f(f(c)), f(f(f(c))), ...\\)<\/span>.\nIf the absolute value of these numbers stays bounded, then <span class=\"mathjax mathjax--inline\">\\(c\\)<\/span> belongs to the Mandelbrot set.\nIf these numbers keep on growing in absolute value, then <span class=\"mathjax mathjax--inline\">\\(c\\)<\/span> does not belong to the set.<\/p>\n<p>After learning how to create the Mandelbrot set I put that knowledge to practice, making use of Python.<\/p>\n<p>The script below uses <code>pygame<\/code> to create a simple rendering of the Mandelbrot set.\nThe image will be black and white and you need to use <kbd>Ctrl<\/kbd> + C to stop the script after you're done looking at the image.<\/p>\n<pre><code class=\"language-py\">import pygame\n\nWIDTH = HEIGHT = 400\n\nscreen = pygame.display.set_mode((WIDTH, HEIGHT))\n\ndef f(z, c):\n    return z**2 + c\n\nMAX_ITER = 50\nfor x in range(WIDTH):\n    for y in range(HEIGHT):\n        re = 3 * x \/ WIDTH - 2.3\n        im = 3 * y \/ HEIGHT - 1.5\n        z = c = complex(re, im)\n        iter = 0\n        while iter &lt; MAX_ITER and abs(z) &lt; 2:\n            z = f(z, c)\n            iter += 1\n\n        if abs(z) &lt; 2:\n            screen.set_at((x, y), pygame.Color(0, 0, 0))\n        else:\n            screen.set_at((x, y), pygame.Color(255, 255, 255))\n\npygame.display.flip()\npygame.image.save(screen, \"bw.png\")\n\nwhile True:\n    for ev in pygame.event.get():\n        pass<\/code><\/pre>\n<p>This will open said pygame window and it will save an image <code>bw.png<\/code> with the rendering:<\/p>\n<figure class=\"image-caption\"><img title=\"Black and white rendering of the Mandelbrot set.\" alt=\"A black and white rendering of the Mandelbrot set, a well-known fractal, rendered with Python and pygame.\" src=\"\/user\/pages\/02.blog\/mandelbrot\/_bw.webp\"><figcaption class=\"\">Black and white rendering of the Mandelbrot set.<\/figcaption><\/figure><p>To make this slightly more interesting, we can create a list with shades of gray and assign each shade to an iteration number, so that the colour a pixel is coloured in depends on how quickly the <code>while<\/code> loop was broken.\nTo achieve this, we need to modify the middle section of the code:<\/p>\n<pre><code class=\"language-py\"># We added this.\nGRAYS = list(\n    reversed(\n        [pygame.Color(*(int(255 * i \/ MAX_ITER),) * 3) for i in range(MAX_ITER + 1)]\n    )\n)\n\nfor x in range(WIDTH):\n    for y in range(HEIGHT):\n        re = 3 * x \/ WIDTH - 2.3\n        im = 3 * y \/ HEIGHT - 1.5\n        z = c = complex(re, im)\n        iter = 0\n        while iter &lt; MAX_ITER and abs(z) &lt; 2:\n            z = f(z, c)...<\/code><\/pre>","summary":"In this article we explore how we can write a simple Python script to render the Mandelbrot set, a well-known fractal.","date_modified":"2025-07-23T16:49:02+02:00","tags":["mathematics","programming","python","fractals","visualisation","pygame"],"image":"\/user\/pages\/02.blog\/mandelbrot\/thumbnail.webp"}]}
