Skip to content

Instantly share code, notes, and snippets.

@jonocarroll
Last active April 7, 2022 11:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonocarroll/27f9b57332424ea50ec2970e74d8e3b3 to your computer and use it in GitHub Desktop.
Save jonocarroll/27f9b57332424ea50ec2970e74d8e3b3 to your computer and use it in GitHub Desktop.
Julia interpolation animation
## Inspired by
## https://twitter.com/ted_dunning/status/1435027697386721280?s=20&t=cDVb0XOQRJeOjXoTrOz54w
using Plots
## These are required to be imported to write methods for them
import Base:*
import Base:+
## Define an interpolation function between a and b
## parameterised by some t
interpolate(a, b) = t -> ((1.0-t)*a + t*b)
## This can act on anything, but with Julia's dispatch,
## that includes functions
## The only operations needed for this are
+(f::Function, g::Function) = x -> f(x) + g(x)
*(t::Number, g::Function) = x -> t * g(x)
## Then we can interpolate between two points
bz1(p1, p2) = interpolate(p1, p2)
## And interpolate between the interpolations
bz2(p1, p2, p3) = interpolate(bz1(p1, p2), bz1(p2, p3))
## And interpolate between the interpolations again
bz3(p1, p2, p3, p4) = interpolate(bz2(p1, p2, p3), bz2(p2, p3, p4))
###
## Defining some points
p1 = [0,0]
p2 = [1,2]
p3 = [2,2]
p4 = [1.5,0]
## The combined interpolation between pairs then pairs then pairs
## will trace out these points
dots = map(i -> bz3(p1, p2, p3, p4)(i)(i)(i),collect(0:0.05:1))
dots = hcat(dots...)
## Animating the points and the lines between them
anim1 = @animate for t in collect(vcat(0:0.01:1,1:-0.01:0))
a = bz3(p1, p2, p3, p4)(t)(t)(t);
b1 = bz2(p1, p2, p3)(t)(t);
b2 = bz2(p2, p3, p4)(t)(t);
c1 = bz1(p1, p2)(t);
c2 = bz1(p2, p3)(t);
c3 = bz1(p3, p4)(t);
stars = hcat(p1, p2, p3, p4);
diamond1 = hcat(c1, c2);
diamond2 = hcat(c2, c3);
square = hcat(b1, b2);
plot(xlim = (-0.1,2.5), ylim = (-0.1,2.5), legend = false)
scatter!(dots[1,:], dots[2,:], markersize = 2)
plot!(diamond1[1,:], diamond1[2,:], markersize = 10, markershape = :diamond, color = :green)
plot!(diamond2[1,:], diamond2[2,:], markersize = 10, markershape = :diamond, color = :green)
plot!(square[1,:], square[2,:], markersize = 10, markershape = :square, color = :blue)
plot!(stars[1,:], stars[2,:], markersize = 10, markershape = :star, color = :purple)
scatter!(Tuple(a), markersize = 10, markershape = :circle, markercolor = :red)
end
gif(anim1, "julia_interpolate_1.gif", fps = 24)
###
## Again, with some different points!
p1 = [0.5,1]
p2 = [0.25,2.2]
p3 = [1.8,1.8]
p4 = [1.5,0.2]
dots = map(i -> bz3(p1, p2, p3, p4)(i)(i)(i),collect(0:0.05:1))
dots = hcat(dots...)
anim2 = @animate for t in collect(vcat(0:0.01:1,1:-0.01:0))
a = bz3(p1, p2, p3, p4)(t)(t)(t);
b1 = bz2(p1, p2, p3)(t)(t);
b2 = bz2(p2, p3, p4)(t)(t);
c1 = bz1(p1, p2)(t);
c2 = bz1(p2, p3)(t);
c3 = bz1(p3, p4)(t);
stars = hcat(p1, p2, p3, p4);
diamond1 = hcat(c1, c2);
diamond2 = hcat(c2, c3);
square = hcat(b1, b2);
plot(xlim = (-0.1,2.5), ylim = (-0.1,2.5), legend = false)
scatter!(dots[1,:], dots[2,:], markersize = 2)
plot!(diamond1[1,:], diamond1[2,:], markersize = 10, markershape = :diamond, color = :green)
plot!(diamond2[1,:], diamond2[2,:], markersize = 10, markershape = :diamond, color = :green)
plot!(square[1,:], square[2,:], markersize = 10, markershape = :square, color = :blue)
plot!(stars[1,:], stars[2,:], markersize = 10, markershape = :star, color = :purple)
scatter!(Tuple(a), markersize = 10, markershape = :circle, markercolor = :red)
end
gif(anim2, "julia_interpolate_2.gif", fps = 24)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment