2024-07-07 20:43:32 +00:00
== Chapter 5: Programming Fractals
=== Introduction
2024-07-07 21:02:46 +00:00
Fractals are complex patterns that are self-similar across different scales. They are fascinating both in their mathematical properties and their visual appeal. In this chapter, we will explore how to program fractals using Elixir and Go, focusing on some of the most famous fractal patterns such as the Mandelbrot set and the Sierpinski triangle.
2024-07-07 20:43:32 +00:00
=== The Mandelbrot Set
The Mandelbrot set is a set of complex numbers that produces a distinctive and famous fractal shape. The set is defined by iterating the function:
[stem]
++++
z_{n+1} = z_n^2 + c
++++
==== Plotting the Mandelbrot Set in Elixir
Let's start with a basic Elixir program to plot the Mandelbrot set.
[source,elixir]
----
defmodule Mandelbrot do
def mandelbrot(c, max_iter) do
iterate(c, 0, 0, max_iter)
end
defp iterate(_c, _z, n, max_iter) when n >= max_iter, do: n
defp iterate(c, z, n, max_iter) when abs(z) > 2, do: n
defp iterate(c, z, n, max_iter) do
iterate(c, z*z + c, n + 1, max_iter)
end
def mandelbrot_set(xmin, xmax, ymin, ymax, width, height, max_iter) do
for x <- 0..(width-1), y <- 0..(height-1) do
r = xmin + (xmax - xmin) * x / width
i = ymin + (ymax - ymin) * y / height
c = Complex.new(r, i)
{x, y, mandelbrot(c, max_iter)}
end
end
end
plot = Mandelbrot.mandelbrot_set(-2.0, 1.0, -1.5, 1.5, 800, 800, 256)
:Gnuplot.plot(plot)
----
2024-07-07 21:02:46 +00:00
==== Plotting the Mandelbrot Set in Go
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
Here's a Go program to plot the Mandelbrot set.
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
[source,go]
2024-07-07 20:43:32 +00:00
----
2024-07-07 21:02:46 +00:00
package main
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
import (
"image"
"image/color"
"image/png"
"math/cmplx"
"os"
)
func mandelbrot(c complex128, maxIter int) int {
z := complex(0, 0)
for n := 0; n < maxIter; n++ {
z = z*z + c
if cmplx.Abs(z) > 2 {
return n
}
}
return maxIter
2024-07-07 20:43:32 +00:00
}
2024-07-07 21:02:46 +00:00
func mandelbrotSet(xmin, xmax, ymin, ymax float64, width, height, maxIter int) *image.Gray {
img := image.NewGray(image.Rect(0, 0, width, height))
for py := 0; py < height; py++ {
for px := 0; px < width; px++ {
x := float64(px)/float64(width)*(xmax-xmin) + xmin
y := float64(py)/float64(height)*(ymax-ymin) + ymin
c := complex(x, y)
m := mandelbrot(c, maxIter)
img.SetGray(px, py, color.Gray{255 - uint8(m)})
}
}
return img
}
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
func main() {
xmin, xmax, ymin, ymax := -2.0, 1.0, -1.5, 1.5
width, height := 800, 800
maxIter := 256
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
img := mandelbrotSet(xmin, xmax, ymin, ymax, width, height, maxIter)
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
file, _ := os.Create("mandelbrot.png")
defer file.Close()
png.Encode(file, img)
}
2024-07-07 20:43:32 +00:00
----
=== The Sierpinski Triangle
The Sierpinski triangle is a fractal that is formed by recursively subdividing an equilateral triangle into smaller equilateral triangles.
==== Plotting the Sierpinski Triangle in Elixir
Here is an Elixir program to plot the Sierpinski triangle using recursion.
[source,elixir]
----
defmodule Sierpinski do
def draw_triangle(x, y, size, depth, canvas) when depth == 0 do
triangle = [{x, y}, {x + size / 2, y + size * :math.sqrt(3) / 2}, {x + size, y}]
:egd.filled_polygon(canvas, triangle, :egd.color(:black))
end
def draw_triangle(x, y, size, depth, canvas) do
draw_triangle(x, y, size / 2, depth - 1, canvas)
draw_triangle(x + size / 2, y, size / 2, depth - 1, canvas)
draw_triangle(x + size / 4, y + size * :math.sqrt(3) / 4, size / 2, depth - 1, canvas)
end
end
{:ok, canvas} = :egd.create(800, 800)
Sierpinski.draw_triangle(0, 0, 800, 5, canvas)
:image.create(:png, canvas)
----
2024-07-07 21:02:46 +00:00
==== Plotting the Sierpinski Triangle in Go
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
Here is a Go program to plot the Sierpinski triangle using recursion.
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
[source,go]
2024-07-07 20:43:32 +00:00
----
2024-07-07 21:02:46 +00:00
package main
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
import (
"image"
"image/color"
"image/png"
"os"
)
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
func drawTriangle(img *image.Gray, x, y, size, depth int) {
if depth == 0 {
drawFilledPolygon(img, [][]int{{x, y}, {x + size / 2, y + int(float64(size) * 0.866)}, {x + size, y}}, 0)
} else {
drawTriangle(img, x, y, size / 2, depth - 1)
drawTriangle(img, x + size / 2, y, size / 2, depth - 1)
drawTriangle(img, x + size / 4, y + int(float64(size) * 0.866 / 2), size / 2, depth - 1)
}
2024-07-07 20:43:32 +00:00
}
2024-07-07 21:02:46 +00:00
func drawFilledPolygon(img *image.Gray, points [][]int, value uint8) {
for i := 0; i < len(points); i++ {
x0, y0 := points[i][0], points[i][1]
x1, y1 := points[(i + 1) % len(points)][0], points[(i + 1) % len(points)][1]
drawLine(img, x0, y0, x1, y1, value)
}
2024-07-07 20:43:32 +00:00
}
2024-07-07 21:02:46 +00:00
func drawLine(img *image.Gray, x0, y0, x1, y1 int, value uint8) {
dx := x1 - x0
dy := y1 - y0
steps := max(abs(dx), abs(dy))
if steps == 0 {
img.SetGray(x0, y0, color.Gray{value})
return
}
for i := 0; i <= steps; i++ {
x := x0 + i * dx / steps
y := y0 + i * dy / steps
img.SetGray(x, y, color.Gray{value})
}
}
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
func main() {
width, height := 800, 800
img := image.NewGray(image.Rect(0, 0, width, height))
drawTriangle(img, 0, 0, width, 5)
2024-07-07 20:43:32 +00:00
2024-07-07 21:02:46 +00:00
file, _ := os.Create("sierpinski.png")
defer file.Close()
png.Encode(file, img)
}
2024-07-07 20:43:32 +00:00
----
=== Conclusion
Fractals are an excellent way to understand the beauty and complexity of mathematical patterns. By programming these patterns, we not only appreciate their aesthetic appeal but also gain insights into their mathematical properties.
=== Further Reading
For more information on fractals and programming, check out the following resources:
* https://en.wikipedia.org/wiki/Mandelbrot_set[Mandelbrot Set - Wikipedia]
* https://en.wikipedia.org/wiki/Sierpinski_triangle[Sierpinski Triangle - Wikipedia]
=== References
1. Mandelbrot, B. B. (1982). _The Fractal Geometry of Nature_. New York: W.H. Freeman and Company.
2. Peitgen, H.-O., Jürgens, H., & Saupe, D. (1992). _Chaos and Fractals: New Frontiers of Science_. New York: Springer.
=== Appendix
==== Image and Code Credits
2024-07-07 21:02:46 +00:00
* Mandelbrot Set: Code adapted from various fractal tutorials in Elixir and Go.
* Sierpinski Triangle: Code adapted from various fractal tutorials in Elixir and Go.