using QuadGK
= range(-5, 5, 200)
z fx(z) = sin(z^2)
fy(z) = cos(z^2)
= [quadgk(fx, 0, t)[1] for t in z]
x = [quadgk(fy, 0, t)[1] for t in z]
y splot("""unset zeroaxis
set tics border
set xyplane at -5
set view 65,35
set border 4095
set xtics offset 0, -0.5""",
"w l lc 'black' lw 1.5") x, y, z,
Examples
3-D Euler spiral (Clothoid)
Waterfall
Inspired by this Julia Discourse discussion.
= -15:0.1:15
x = 0:30
y = [exp(-(x-0.5*(y-15))^2) for x in x, y in y]
u1data = fill(0.0, length(x))
Zf = Figure()
f set!(f(1), """set zrange [0:1.5]
Gaston. set tics out
set ytics border
set xyplane at 0
set view 45,17
set xlabel 'ξ'
set ylabel 't' offset -2.5
set zlabel '|u|' offset -0.85
set border 21
set size 1, 1.3""")
for i in reverse(eachindex(y))
= fill(y[i], length(x))
Y = u1data[:,i]
Z splot!(x, Y, Z, Zf, Z, "w zerrorfill lc 'black' fillstyle solid 1.0 fc 'white'")
end
f
Vector field
Inspired by this post in gnuplotting.org.
= 15 # samples in x direction
xr = 15 # samples in y direction
yr
# parameters
= 1
x01 = 0
y01 = 1
q1 = -1
x02 = 0
y02 = -1
q2 = 0.22
scaling
# equations
r(x,y) = sqrt(x*x+y*y)
v1(x,y) = q1/(r(x-x01,y-y01))
v2(x,y) = q2/(r(x-x02,y-y02))
v(x,y) = v1(x,y)+v2(x,y)
e1x(x,y) = q1*x/r(x,y)^3
e1y(x,y) = q1*y/r(x,y)^3
e2x(x,y) = q2*x/r(x,y)^3
e2y(x,y) = q2*y/r(x,y)^3
ex(x,y) = e1x(x-x01,y-y01)+e2x(x-x02,y-y02)
ey(x,y) = e1y(x-x01,y-y01)+e2y(x-x02,y-y02)
enorm(x,y) = sqrt(ex(x,y)^2 + ey(x,y)^2)
dx(x,y) = scaling*ex(x,y)/enorm(x,y)
dy(x,y) = scaling*ey(x,y)/enorm(x,y)
# initialize data vectors
= zeros(xr*yr)
d1 = zeros(xr*yr)
d2 = zeros(xr*yr)
d3 = zeros(xr*yr)
d4 = zeros(xr*yr)
d5
# calculations
for X in range(-2, 2, length=xr)
for Y in range(-1.8, 1.8, length=yr)
push!(d1, X-dx(X,Y)/2)
push!(d2, Y-dy(X,Y)/2)
push!(d3, dx(X,Y))
push!(d4, dy(X,Y))
push!(d5, v(X,Y))
end
end
@plot({palette = :linear_kry_5_95_c72_n256}, :nocb,
d1, d2, d3, d4, d5,"with vectors head size 0.08,20,60 filled lc palette")
Line color from palette
= -2π:0.05:2π
x @plot {palette = :ice} x sin.(3x) x "w l notitle lw 3 lc palette"
Variable marker size and color
= 0:0.1:6π
x splot("unset colorbox",
cos.(x), sin.(x), x./10,
x, "w p", "ps variable", "pt 7", "lc palette")
Filled curves
Filled transparent curves in 2-D
pois(λ, k) = (λ^k)*exp(-λ)/factorial(k)
= "set style fill transparent solid 0.4 noborder \nset title 'Poisson PMF'"
s plot(s, 0:15, k -> pois(4, k), "w filledcu x1 lc 'cyan' t 'λ = 4'")
plot!(0:15, k -> pois(6, k), "w filledcu x1 lc 'blue' t 'λ = 6'")
plot!(0:15, k -> pois(8, k), "w filledcu x1 lc 'pink' t 'λ = 8'")
Fill between two curves
= range(-10, 10, 100)
x = sin.(x) .- 0.5
y1 = sin.(x) .+ 0.5
y2 plot(x, y1, y2, "w filledcu lc 'turquoise'")
Filled curve in 3-D
= 0.:0.05:3;
x = 0.:0.05:3;
y = @. sin(x) * exp(-(x+y))
z @gpkw splot(:labels, {style = "fill transparent solid 0.3", xyplane = "at 0", grid, lt = :Set1_5},
.*0, z,
x, y, z, z"w zerror t 'Data'")
splot!(x.*0, y, z, "w l lw 3")
splot!(x, y.*0, z, "w l lw 3")
Here, Set1_5
is a color scheme from ColorSchemes.jl.
Spheres
Wireframe
= range(0, 2π, length = 100)
Θ = range(0, π, length = 20)
Φ = 0.8
rd = [rd*cos(θ)*sin(ϕ) for θ in Θ, ϕ in Φ]
x = [rd*sin(θ)*sin(ϕ) for θ in Θ, ϕ in Φ]
y = [rd*cos(ϕ) for θ in Θ, ϕ in Φ]
z @gpkw splot({view = "equal xyz", pm3d = "depthorder", hidden3d},
x, y, z,= "l", lc = Q"turquoise"}) {w
Surface
= range(0, 2π, length = 100)
Θ = range(0, π, length = 100)
Φ = 0.8
rd = [rd*cos(θ)*sin(ϕ) for θ in Θ, ϕ in Φ]
x = [rd*sin(θ)*sin(ϕ) for θ in Θ, ϕ in Φ]
y = [rd*cos(ϕ) for θ in Θ, ϕ in Φ]
z @splot({style = "fill transparent solid 1",
= :summer,
palette = "equal xyz",
view = "depthorder"},
pm3d
x, y, z,"w pm3d")
Torus
= range(-π, π, length = 50)
U = range(-π, π, length = 100)
V = 0.5
rd = [1+cos(u)+rd*cos(u)*cos(v) for u in U, v in V]
x = [rd*sin(v) for u in U, v in V]
y = [sin(u)+rd*sin(u)*cos(v) for u in U, v in V]
z = """set object rectangle from screen 0,0 to screen 1,1 behind fillcolor 'black' fillstyle solid noborder
settings set pm3d depthorder
set style fill transparent solid 0.5
set pm3d lighting primary 0.05 specular 0.2
set view 108,2
unset border
set xyplane 0
unset tics
unset colorbox"""
@splot(settings, {palette = :cool}, x, y, z, "w pm3d")
Interlocking torii
= LinRange(-π, pi, 100)
U = LinRange(-π, pi, 20)
V = [cos(u) + .5 * cos(u) * cos(v) for u in U, v in V]
x = [sin(u) + .5 * sin(u) * cos(v) for u in U, v in V]
y = [.5 * sin(v) for u in U, v in V]
z @gpkw surf({palette = :dense,
= "depthorder",
pm3d = false,
colorbox = :false,
key = :false,
tics = 0,
border = "60, 30, 1.5, 0.9",
view = "fill transparent solid 0.7"},
style ', y', z')
x= [1 + cos(u) + .5 * cos(u) * cos(v) for u in U, v in V]
x = [.5 * sin(v) for u in U, v in V]
y = [sin(u) + .5 * sin(u) * cos(v) for u in U, v in V]
z surf!(x', y', z')
See more torus examples in the included Pluto notebook.
Contours
Surface with contours
= y = -10:0.5:10
x f1(x, y) = cos.(x./2).*sin.(y./2)
surf("""set hidden3d
set contour base
set cntrparam levels 10
unset key""",
x, y, f1,"lc 'turquoise'")
Egg-shaped contours
= -1:0.05:1
x = -1.5:0.05:2
y egg(x,y) = x^2 + y^2/(1.4 + y/5)^2
= [egg(x,y) for x in x, y in y]
segg @gpkw contour({palette = :cool,
= "levels incremental 0,0.01,1",
cntrparam = "fix",
auto = (-1.2, 1.2),
xrange = (-1.5, 2),
yrange = (0, 1),
cbrange = "'x'",
xlabel = "'y'",
ylabel = "ratio -1"},
size ',
x, y, segg"w l lc palette",
= false) labels
3D Tubes
Wireframe
= range(0, 10π, length = 80)
U = range(0, 2π, length = 10)
V = [(1-0.1*cos(v))*cos(u) for u in U, v in V]
x = [(1-0.1*cos(v))*sin(u) for u in U, v in V]
y = [0.2*(sin(v) + u/1.7 - 10) for u in U, v in V]
z = @gpkw {pm3d = "depthorder",
settings = "fill transparent solid 1",
style = "equal xyz",
view = -0.05,
xyplane = :ice,
palette = (-1.2, 1.2),
xrange = (-1.2, 1.2),
yrange = false,
colorbox
hidden3d,= (70, 79)}
view @splot(settings, x, y, z, "w l lc 'turquoise'")
Surface
@splot(settings, x, y, z, "w pm3d")
Animations
Lorenz attractor
This example is adapted from https://docs.makie.org/stable/#example. A few notes on the adaptation to Gaston:
- The camera animation is achieved by changing the
view
setting every frame. - Each frame,
Npoints
coordinates are added to the plot. The animation consists ofNframes
frames. - The coloring of the attractor is different than in most 3-D plots. Normally, the color of a point depends on its
z
coordinate. In this case, thez
coordinate is not an amplitude, since the curve lives in a state space. Therefore, the color palette will be applied along the length of the curve, with points nearer the start given colors at the start of the palette. To achieve this, we useColorSchemes.resample
to create a new palette with the same number of colors as there are points in the curve. Then,Gaston.hex
is used to convert these colors to decimal numbers. Finally, the colors are used as a fourth column of data and the line color is set tolc rgb variable
.
using ColorSchemes
Base.@kwdef mutable struct Lorenz
::Float64 = 0.01
dt::Float64 = 10
σ::Float64 = 28
ρ::Float64 = 8/3
β::Float64 = 1
x::Float64 = 1
y::Float64 = 1
zend
function step!(l::Lorenz)
= l.σ * (l.y - l.x)
dx = l.x * (l.ρ - l.z) - l.y
dy = l.x * l.y - l.β * l.z
dz += l.dt * dx
l.x += l.dt * dy
l.y += l.dt * dz
l.z return (l.x, l.y, l.z)
end
= 120
Nframes = 50
Npoints = Lorenz()
attractor = Float64[];
x = Float64[];
y = Float64[];
z
= @gpkw {xrange = (-30, 30),
s = (-30, 30),
yrange = (0, 60),
zrange = "offset -1.2,0",
xtics = "add ('' -30, '' 30)",
xtics = "offset 1.2,0",
ytics = "add ('' -30, '' 30)",
ytics = "-0.1, -0.1",
origin = "1.2, 1.2",
size = "rectangle from screen 0,0 to screen 1,1 fillcolor 'black' behind",
object = "back lc rgb '#eeeeee' lt 1 lw 1.5",
border = "equal xyz",
view = "at 0"}
xyplane
= splot(s, 1, 1, 1)
f
for i = 1:Nframes
for j = 1:Npoints
step!(attractor)
push!(x, attractor.x);
push!(y, attractor.y);
push!(z, attractor.z)
end
= resample(ColorSchemes.inferno, length(x))
cs splot(f[i],
"set view 70, $(45 + 17 * sin(2pi * i / Nframes))",
s, hex(cs),
x, y, z, Gaston."w l notitle lc rgb variable")
end
save(f, filename = "lorenz.webp", term = "webp animate loop 0 size 640,480")
3-D spiral
= 0:0.1:10pi
z = 5
step = "lc 'turquoise' lw 3 notitle"
cc = @gpkw {zrange = (0,30), xrange = (-1.2, 1.2), yrange = (-1.2, 1.2)}
ac = scatter3(ac, :notics, :labels, cos.(z[1:step]), sin.(z[1:step]), z[1:step], cc)
F = Figure()
frame for i = 2:60
= scatter3(ac, :notics, :labels, cos.(z[1:i*step]), sin.(z[1:i*step]), z[1:i*step], cc)
frame push!(F, frame)
end
for i = 60:-1:1
= scatter3(ac, :notics, :labels, cos.(z[1:i*step]), sin.(z[1:i*step]), z[1:i*step], cc)
frame push!(F, frame)
end
save(F, filename = "3dspiral.webp", term = "webp animate loop 0 size 640,480")
Splash
= y = -15:0.4:15
x = @gpkw {title = Q"Splash",
ac = :cool,
palette = (-0.2, 1),
cbrange = (-0.3, 1),
zrange = true}
hidden3d = splot(ac, x, y, (x, y) -> sin(sqrt(x*x+y*y))/sqrt(x*x+y*y), "w pm3d")
F = Figure()
frame for i = 1:-0.1:-1
= splot(ac, x, y, (x,y) -> i*sin(sqrt(x*x+y*y))/sqrt(x*x+y*y), "w pm3d");
frame push!(F, frame)
end
for i = -0.9:0.1:1
= splot(ac, x, y, (x,y) -> i*sin(sqrt(x*x+y*y))/sqrt(x*x+y*y), "w pm3d");
frame push!(F, frame)
end
save(F, filename = "3dsplash.webp", term = "webp animate loop 0 size 640,480")