using QuadGK
z = range(-5, 5, 200)
fx(z) = sin(z^2)
fy(z) = cos(z^2)
x = [quadgk(fx, 0, t)[1] for t in z]
y = [quadgk(fy, 0, t)[1] for t in z]
splot("""unset zeroaxis
set tics border
set xyplane at -5
set view 65,35
set border 4095
set xtics offset 0, -0.5""",
x, y, z, "w l lc 'black' lw 1.5")Examples
3-D Euler spiral (Clothoid)
Waterfall
Inspired by this Julia Discourse discussion.
x = -15:0.1:15
y = 0:30
u1data = [exp(-(x-0.5*(y-15))^2) for x in x, y in y]
Zf = fill(0.0, length(x))
f = Figure()
Gaston.set!(f(1), """set zrange [0:1.5]
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))
Y = fill(y[i], length(x))
Z = u1data[:,i]
splot!(x, Y, Z, Zf, Z, "w zerrorfill lc 'black' fillstyle solid 1.0 fc 'white'")
end
fVector field
Inspired by this post in gnuplotting.org.
xr = 15 # samples in x direction
yr = 15 # samples in y direction
# parameters
x01 = 1
y01 = 0
q1 = 1
x02 = -1
y02 = 0
q2 = -1
scaling = 0.22
# 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
d1 = zeros(xr*yr)
d2 = zeros(xr*yr)
d3 = zeros(xr*yr)
d4 = zeros(xr*yr)
d5 = zeros(xr*yr)
# 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
x = -2π:0.05:2π
@plot {palette = :ice} x sin.(3x) x "w l notitle lw 3 lc palette"Variable marker size and color
x = 0:0.1:6π
splot("unset colorbox",
x, cos.(x), sin.(x), x./10,
"w p", "ps variable", "pt 7", "lc palette")Filled curves
Filled transparent curves in 2-D
pois(λ, k) = (λ^k)*exp(-λ)/factorial(k)
s = "set style fill transparent solid 0.4 noborder \nset title 'Poisson PMF'"
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
x = range(-10, 10, 100)
y1 = sin.(x) .- 0.5
y2 = sin.(x) .+ 0.5
plot(x, y1, y2, "w filledcu lc 'turquoise'")Filled curve in 3-D
x = 0.:0.05:3;
y = 0.:0.05:3;
z = @. sin(x) * exp(-(x+y))
@gpkw splot(:labels, {style = "fill transparent solid 0.3", xyplane = "at 0", grid, lt = :Set1_5},
x, y, z, z.*0, 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)
rd = 0.8
x = [rd*cos(θ)*sin(ϕ) for θ in Θ, ϕ in Φ]
y = [rd*sin(θ)*sin(ϕ) for θ in Θ, ϕ in Φ]
z = [rd*cos(ϕ) for θ in Θ, ϕ in Φ]
@gpkw splot({view = "equal xyz", pm3d = "depthorder", hidden3d},
x, y, z,
{w = "l", lc = Q"turquoise"})Surface
Θ = range(0, 2π, length = 100)
Φ = range(0, π, length = 100)
rd = 0.8
x = [rd*cos(θ)*sin(ϕ) for θ in Θ, ϕ in Φ]
y = [rd*sin(θ)*sin(ϕ) for θ in Θ, ϕ in Φ]
z = [rd*cos(ϕ) for θ in Θ, ϕ in Φ]
@splot({style = "fill transparent solid 1",
palette = :summer,
view = "equal xyz",
pm3d = "depthorder"},
x, y, z,
"w pm3d")Torus
U = range(-π, π, length = 50)
V = range(-π, π, length = 100)
rd = 0.5
x = [1+cos(u)+rd*cos(u)*cos(v) for u in U, v in V]
y = [rd*sin(v) for u in U, v in V]
z = [sin(u)+rd*sin(u)*cos(v) for u in U, v in V]
settings = """set object rectangle from screen 0,0 to screen 1,1 behind fillcolor 'black' fillstyle solid noborder
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
U = LinRange(-π, pi, 100)
V = LinRange(-π, pi, 20)
x = [cos(u) + .5 * cos(u) * cos(v) for u in U, v in V]
y = [sin(u) + .5 * sin(u) * cos(v) for u in U, v in V]
z = [.5 * sin(v) for u in U, v in V]
@gpkw surf({palette = :dense,
pm3d = "depthorder",
colorbox = false,
key = :false,
tics = :false,
border = 0,
view = "60, 30, 1.5, 0.9",
style = "fill transparent solid 0.7"},
x', y', z')
x = [1 + cos(u) + .5 * cos(u) * cos(v) for u in U, v in V]
y = [.5 * sin(v) for u in U, v in V]
z = [sin(u) + .5 * sin(u) * cos(v) for u in U, v in V]
surf!(x', y', z')See more torus examples in the included Pluto notebook.
Contours
Surface with contours
x = y = -10:0.5:10
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
x = -1:0.05:1
y = -1.5:0.05:2
egg(x,y) = x^2 + y^2/(1.4 + y/5)^2
segg = [egg(x,y) for x in x, y in y]
@gpkw contour({palette = :cool,
cntrparam = "levels incremental 0,0.01,1",
auto = "fix",
xrange = (-1.2, 1.2),
yrange = (-1.5, 2),
cbrange = (0, 1),
xlabel = "'x'",
ylabel = "'y'",
size = "ratio -1"},
x, y, segg',
"w l lc palette",
labels = false)3D Tubes
Wireframe
U = range(0, 10π, length = 80)
V = range(0, 2π, length = 10)
x = [(1-0.1*cos(v))*cos(u) for u in U, v in V]
y = [(1-0.1*cos(v))*sin(u) for u in U, v in V]
z = [0.2*(sin(v) + u/1.7 - 10) for u in U, v in V]
settings = @gpkw {pm3d = "depthorder",
style = "fill transparent solid 1",
view = "equal xyz",
xyplane = -0.05,
palette = :ice,
xrange = (-1.2, 1.2),
yrange = (-1.2, 1.2),
colorbox = false,
hidden3d,
view = (70, 79)}
@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
viewsetting every frame. - Each frame,
Npointscoordinates are added to the plot. The animation consists ofNframesframes. - The coloring of the attractor is different than in most 3-D plots. Normally, the color of a point depends on its
zcoordinate. In this case, thezcoordinate 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.resampleto create a new palette with the same number of colors as there are points in the curve. Then,Gaston.hexis 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
dt::Float64 = 0.01
σ::Float64 = 10
ρ::Float64 = 28
β::Float64 = 8/3
x::Float64 = 1
y::Float64 = 1
z::Float64 = 1
end
function step!(l::Lorenz)
dx = l.σ * (l.y - l.x)
dy = l.x * (l.ρ - l.z) - l.y
dz = l.x * l.y - l.β * l.z
l.x += l.dt * dx
l.y += l.dt * dy
l.z += l.dt * dz
return (l.x, l.y, l.z)
end
Nframes = 120
Npoints = 50
attractor = Lorenz()
x = Float64[];
y = Float64[];
z = Float64[];
s = @gpkw {xrange = (-30, 30),
yrange = (-30, 30),
zrange = (0, 60),
xtics = "offset -1.2,0",
xtics = "add ('' -30, '' 30)",
ytics = "offset 1.2,0",
ytics = "add ('' -30, '' 30)",
origin = "-0.1, -0.1",
size = "1.2, 1.2",
object = "rectangle from screen 0,0 to screen 1,1 fillcolor 'black' behind",
border = "back lc rgb '#eeeeee' lt 1 lw 1.5",
view = "equal xyz",
xyplane = "at 0"}
f = splot(s, 1, 1, 1)
for i = 1:Nframes
for j = 1:Npoints
step!(attractor)
push!(x, attractor.x);
push!(y, attractor.y);
push!(z, attractor.z)
end
cs = resample(ColorSchemes.inferno, length(x))
splot(f[i],
s, "set view 70, $(45 + 17 * sin(2pi * i / Nframes))",
x, y, z, Gaston.hex(cs),
"w l notitle lc rgb variable")
end
save(f, filename = "lorenz.webp", term = "webp animate loop 0 size 640,480")3-D spiral
z = 0:0.1:10pi
step = 5
cc = "lc 'turquoise' lw 3 notitle"
ac = @gpkw {zrange = (0,30), xrange = (-1.2, 1.2), yrange = (-1.2, 1.2)}
F = scatter3(ac, :notics, :labels, cos.(z[1:step]), sin.(z[1:step]), z[1:step], cc)
frame = Figure()
for i = 2:60
frame = scatter3(ac, :notics, :labels, cos.(z[1:i*step]), sin.(z[1:i*step]), z[1:i*step], cc)
push!(F, frame)
end
for i = 60:-1:1
frame = scatter3(ac, :notics, :labels, cos.(z[1:i*step]), sin.(z[1:i*step]), z[1:i*step], cc)
push!(F, frame)
end
save(F, filename = "3dspiral.webp", term = "webp animate loop 0 size 640,480")Splash
x = y = -15:0.4:15
ac = @gpkw {title = Q"Splash",
palette = :cool,
cbrange = (-0.2, 1),
zrange = (-0.3, 1),
hidden3d = true}
F = splot(ac, x, y, (x, y) -> sin(sqrt(x*x+y*y))/sqrt(x*x+y*y), "w pm3d")
frame = Figure()
for i = 1:-0.1:-1
frame = splot(ac, x, y, (x,y) -> i*sin(sqrt(x*x+y*y))/sqrt(x*x+y*y), "w pm3d");
push!(F, frame)
end
for i = -0.9:0.1:1
frame = splot(ac, x, y, (x,y) -> i*sin(sqrt(x*x+y*y))/sqrt(x*x+y*y), "w pm3d");
push!(F, frame)
end
save(F, filename = "3dsplash.webp", term = "webp animate loop 0 size 640,480")