Mandelbrot set: Difference between revisions
Content added Content deleted
m (→Normal Map Effect, Mercator Projection and Deep Zoom Images: Much nicer stripes) |
m (→Normal Map Effect, Mercator Projection and Perturbation Theory: Much nicer stripes) |
||
Line 7,978: | Line 7,978: | ||
===Normal Map Effect, Mercator Projection and Perturbation Theory=== |
===Normal Map Effect, Mercator Projection and Perturbation Theory=== |
||
This is a translation of the corresponding Python section: see there for more explanations. 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#Normal_map_effect ''Normal map effect'']). |
This is a translation of the corresponding Python section: see there for more explanations. 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#Normal_map_effect ''Normal map effect'']). See also [https://www.shadertoy.com/view/wtscDX Julia Stripes] on Shadertoy. |
||
<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 7,986: | Line 7,986: | ||
direction, height = 45, 1.5 # direction and height of the incoming light |
direction, height = 45, 1.5 # direction and height of the incoming light |
||
stripes, damping = 5.0, 2.0 # stripe density and damping parameter |
|||
v = exp(direction / 180 * pi * im) # unit 2D vector in this direction |
|||
x = range(0, 2, length=d+1) |
x = range(0, 2, length=d+1) |
||
Line 7,995: | Line 7,995: | ||
Z, dZ, ddZ = zero(C), zero(C), zero(C) |
Z, dZ, ddZ = zero(C), zero(C), zero(C) |
||
D, T = zeros(size(C)), zeros(size(C)) |
D, S, T = zeros(size(C)), zeros(size(C)), zeros(size(C)) |
||
for k in 1:n |
for k in 1:n |
||
M = abs2.(Z) .< abs2(r) |
M = abs2.(Z) .< abs2(r) |
||
S[M], T[M] = S[M] .+ sin.(stripes .* angle.(Z[M])), T[M] .+ 1 |
|||
Z[M], dZ[M], ddZ[M] = Z[M] .^ 2 .+ C[M], 2 .* Z[M] .* dZ[M] .+ 1, 2 .* (dZ[M] .^ 2 .+ Z[M] .* ddZ[M]) |
Z[M], dZ[M], ddZ[M] = Z[M] .^ 2 .+ C[M], 2 .* Z[M] .* dZ[M] .+ 1, 2 .* (dZ[M] .^ 2 .+ Z[M] .* ddZ[M]) |
||
end |
end |
||
Line 8,009: | Line 8,010: | ||
N = abs.(Z) .> 2 # normal map effect 1 (potential function) |
N = abs.(Z) .> 2 # normal map effect 1 (potential function) |
||
P, Q = S[N] ./ T[N], (S[N] .+ sin.(stripes .* angle.(Z[N]))) ./ (T[N] .+ 1) |
|||
F = 1 .- log2.(log.(abs.(Z[N])) ./ log(r)) |
|||
H = P .+ (Q .- P) .* F .* F .* (3 .- 2 .* F) # hermite interpolation |
|||
U = Z[N] ./ dZ[N] # normal vectors to the equipotential lines |
U = Z[N] ./ dZ[N] # normal vectors to the equipotential lines |
||
U, |
U, v = U ./ abs.(U), exp(direction / 180 * pi * im) # unit normal vectors and unit 2D vector |
||
D[N] = max.((real.(U) .* real(v) .+ imag.(U) .* imag(v) .+ (1 .+ H ./ damping) .* height) ./ (1 + height), 0) |
|||
heatmap( |
heatmap(D .^ 1.0, c=:bone_1) |
||
savefig("Mandelbrot_normal_map_1.png") |
savefig("Mandelbrot_normal_map_1.png") |
||
N = abs.(Z) .> 2 # normal map effect 2 (distance estimation) |
N = abs.(Z) .> 2 # normal map effect 2 (distance estimation) |
||
U = Z[N] .* dZ[N] .* ((1 .+ log.(abs.(Z[N]))) .* conj.(dZ[N] .^ 2) .- log.(abs.(Z[N])) .* conj.(Z[N] .* ddZ[N])) |
U = Z[N] .* dZ[N] .* ((1 .+ log.(abs.(Z[N]))) .* conj.(dZ[N] .^ 2) .- log.(abs.(Z[N])) .* conj.(Z[N] .* ddZ[N])) |
||
U = U ./ abs.(U) # unit normal vectors |
U, v = U ./ abs.(U), exp(direction / 180 * pi * im) # unit normal vectors and unit 2D vector |
||
D[N] = max.((real.(U) .* real(v) .+ imag.(U) .* imag(v) .+ height) ./ (1 + height), 0) |
|||
heatmap( |
heatmap(D .^ 1.0, c=:afmhot) |
||
savefig("Mandelbrot_normal_map_2.png")</syntaxhighlight> |
savefig("Mandelbrot_normal_map_2.png")</syntaxhighlight> |
||