mirror of
https://github.com/dunyakirkali/letterpress.git
synced 2025-01-23 03:49:49 +00:00
212 lines
5.7 KiB
Plaintext
212 lines
5.7 KiB
Plaintext
== Chapter 5: Programming Fractals
|
|
|
|
=== Introduction
|
|
|
|
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.
|
|
|
|
=== 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)
|
|
----
|
|
|
|
==== Plotting the Mandelbrot Set in Go
|
|
|
|
Here's a Go program to plot the Mandelbrot set.
|
|
|
|
[source,go]
|
|
----
|
|
package main
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func main() {
|
|
xmin, xmax, ymin, ymax := -2.0, 1.0, -1.5, 1.5
|
|
width, height := 800, 800
|
|
maxIter := 256
|
|
|
|
img := mandelbrotSet(xmin, xmax, ymin, ymax, width, height, maxIter)
|
|
|
|
file, _ := os.Create("mandelbrot.png")
|
|
defer file.Close()
|
|
png.Encode(file, img)
|
|
}
|
|
----
|
|
|
|
=== 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)
|
|
----
|
|
|
|
==== Plotting the Sierpinski Triangle in Go
|
|
|
|
Here is a Go program to plot the Sierpinski triangle using recursion.
|
|
|
|
[source,go]
|
|
----
|
|
package main
|
|
|
|
import (
|
|
"image"
|
|
"image/color"
|
|
"image/png"
|
|
"os"
|
|
)
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
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})
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
width, height := 800, 800
|
|
img := image.NewGray(image.Rect(0, 0, width, height))
|
|
drawTriangle(img, 0, 0, width, 5)
|
|
|
|
file, _ := os.Create("sierpinski.png")
|
|
defer file.Close()
|
|
png.Encode(file, img)
|
|
}
|
|
----
|
|
|
|
=== 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
|
|
|
|
* Mandelbrot Set: Code adapted from various fractal tutorials in Elixir and Go.
|
|
* Sierpinski Triangle: Code adapted from various fractal tutorials in Elixir and Go.
|