Mandelbrot set: Difference between revisions
Content added Content deleted
(→Normalized Counting, Distance Estimation, Mercator Maps and Deep Zoom: Smoothing and normalized iteration numbers replaced by normal maps (sources adjusted).) |
(→Normalized Counting, Distance Estimation, Mercator Maps and Perturbation Theory: Adapted to the Python version.) |
||
Line 6,566: | Line 6,566: | ||
gif(smoothing, "Mandelbrot_smoothing.gif", fps=2)</syntaxhighlight> |
gif(smoothing, "Mandelbrot_smoothing.gif", fps=2)</syntaxhighlight> |
||
=== |
===Distance Estimation, Normal Maps, Mercator Maps and Perturbation Theory === |
||
This is a translation of the corresponding Python section. The Mandelbrot set is represented by distance estimation and normal maps using complex matrices (cf. Arnaud Chéritat: [https://www.math.univ-toulouse.fr/~cheritat/wiki-draw/index.php/Mandelbrot_set#Boundary_detection_methods_via_distance_estimators ''Boundary detection methods via distance estimators''] and [https://www.math.univ-toulouse.fr/~cheritat/wiki-draw/index.php/Mandelbrot_set#Normal_map_effect ''Normal map effect'']). |
|||
This is a translation of the corresponding Python section. The ''e^(-|z|)-smoothing'', ''normalized iteration count'' and ''exterior distance estimation'' algorithms are used. |
|||
<syntaxhighlight lang="julia">using Plots |
<syntaxhighlight lang="julia">using Plots |
||
gr(aspect_ratio=:equal, axis=true, ticks=true, legend=false, dpi=200) |
gr(aspect_ratio=:equal, axis=true, ticks=true, legend=false, dpi=200) |
||
Line 6,573: | Line 6,573: | ||
d, h = 800, 500 # pixel density (= image width) and image height |
d, h = 800, 500 # pixel density (= image width) and image height |
||
n, r = 200, 500 # number of iterations and escape radius (r > 2) |
n, r = 200, 500 # number of iterations and escape radius (r > 2) |
||
height, angle = 1.5, 45 # height factor of the incoming light and direction of this light |
|||
v = exp(angle / 180 * pi * im) # unit 2D vector in this direction |
|||
x = range(0, 2, length=d+1) |
x = range(0, 2, length=d+1) |
||
Line 6,580: | Line 6,583: | ||
C = (2.0 + 1.0im) .* (A' .+ B .* im) .- 0.5 |
C = (2.0 + 1.0im) .* (A' .+ B .* im) .- 0.5 |
||
Z, dZ = zero(C), zero(C) |
Z, dZ, ddZ, U = zero(C), zero(C), zero(C), zero(C) |
||
D, T = zeros(size(C)), zeros(size(C)) |
|||
iteration(Z, dZ, ddZ, C) = Z .^ 2 .+ C, 2 .* Z .* dZ .+ 1, 2 .* (dZ .^ 2 .+ Z .* ddZ) |
|||
for k in 1:n |
for k in 1:n |
||
M = |
M = abs2.(Z) .< abs2(r) |
||
Z[M], dZ[M], ddZ[M] = iteration(Z[M], dZ[M], ddZ[M], C[M]) |
|||
Z[M], dZ[M] = Z[M] .^ 2 .+ C[M], 2 .* Z[M] .* dZ[M] .+ 1 |
|||
end |
end |
||
N = abs.(Z) .> 2 # exterior distance estimation |
|||
⚫ | |||
D[N] = log.(abs.(Z[N])) .* abs.(Z[N]) ./ abs.(dZ[N]) |
|||
⚫ | |||
savefig("Mandelbrot_set_1.png") |
savefig("Mandelbrot_set_1.png") |
||
N = abs.(Z) .> |
N = abs.(Z) .> 2 # normal map (potential function) |
||
U[N] = Z[N] ./ dZ[N] |
|||
T[N] = max.(((real.(U[N]) .* real.(v) .+ imag.(U[N]) .* imag.(v)) ./ abs.(U[N]) .+ height) ./ (1 .+ height), 0) |
|||
heatmap(T .^ |
heatmap(T .^ 1.0, c=:grays) |
||
savefig("Mandelbrot_set_2.png") |
savefig("Mandelbrot_set_2.png") |
||
N = abs.(Z) .> 2 # |
N = abs.(Z) .> 2 # normal map (distance estimation) |
||
U[N] = Z[N] .* dZ[N] .* ((1 .+ log.(abs.(Z[N]))) .* conj.(dZ[N] .^ 2) .- log.(abs.(Z[N])) .* conj.(Z[N] .* ddZ[N])) |
|||
T[N] = max.(((real.(U[N]) .* real.(v) .+ imag.(U[N]) .* imag.(v)) ./ abs.(U[N]) .+ height) ./ (1 .+ height), 0) |
|||
heatmap( |
heatmap(T .^ 1.0, c=:grays) |
||
savefig("Mandelbrot_set_3.png")</syntaxhighlight> |
savefig("Mandelbrot_set_3.png")</syntaxhighlight> |
||
A small change in the code above creates Mercator maps and zoom images of the Mandelbrot set |
A small change in the code above creates Mercator maps and zoom images of the Mandelbrot set. See also the album [https://www.flickr.com/photos/arenamontanus/albums/72157615740829949 Mercator Mandelbrot Maps] by Anders Sandberg. |
||
<syntaxhighlight lang="julia">using Plots |
<syntaxhighlight lang="julia">using Plots |
||
gr(aspect_ratio=:equal, axis=true, ticks=true, legend=false, dpi=200) |
gr(aspect_ratio=:equal, axis=true, ticks=true, legend=false, dpi=200) |
||
Line 6,627: | Line 6,635: | ||
N = abs.(Z) .> 2 # exterior distance estimation |
N = abs.(Z) .> 2 # exterior distance estimation |
||
D[N] = |
D[N] = log.(abs.(Z[N])) .* abs.(Z[N]) ./ abs.(dZ[N]) |
||
heatmap(D' .^ 0.1, c=:nipy_spectral) |
heatmap(D' .^ 0.1, c=:nipy_spectral) |
||
Line 6,685: | Line 6,693: | ||
N = abs.(Z) .> 2 # exterior distance estimation |
N = abs.(Z) .> 2 # exterior distance estimation |
||
D[N] = |
D[N] = log.(abs.(Z[N])) .* abs.(Z[N]) ./ abs.(dZ[N]) |
||
heatmap(D .^ 0.3, c=:nipy_spectral) |
heatmap(D .^ 0.3, c=:nipy_spectral) |
||
Line 6,733: | Line 6,741: | ||
N = abs.(Z) .> 2 # exterior distance estimation |
N = abs.(Z) .> 2 # exterior distance estimation |
||
D[N] = |
D[N] = log.(abs.(Z[N])) .* abs.(Z[N]) ./ abs.(dZ[N]) |
||
heatmap(D' .^ 0.03, c=:nipy_spectral) |
heatmap(D' .^ 0.03, c=:nipy_spectral) |