diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b220a45 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +Manifest.toml +gravities.gif \ No newline at end of file diff --git a/Project.toml b/Project.toml new file mode 100644 index 0000000..e3fa310 --- /dev/null +++ b/Project.toml @@ -0,0 +1,2 @@ +[deps] +Javis = "78b212ba-a7f9-42d4-b726-60726080707e" diff --git a/gravities.jl b/gravities.jl new file mode 100644 index 0000000..cf2a565 --- /dev/null +++ b/gravities.jl @@ -0,0 +1,214 @@ +using Javis + +# Planetary data from: https://nssdc.gsfc.nasa.gov/planetary/factsheet/ +diameters = Dict( + "Mercury" => 4879, + "Venus" => 12104, + "Earth" => 12756, + "Moon" => 3475, + "Mars" => 6792, + "Jupiter" => 142984, + "Saturn" => 120536, + "Uranus" => 51118, + "Neptune" => 49528, + "Pluto" => 2370, +) + + +struct Planet + position::Int # Position from the sun + name::String + gravity::Real # m/s + color::String # total guesstimate + radius::Real # whatever fake units make the viz pretty +end + +# Automatically calculate radius for us. Calculation is totally arbritrary +Planet(pos, name, grav, color) = Planet(pos, name, grav, color, log(diameters[name]) * 2) + +planets = [ + Planet(1, "Mercury", 3.7, "snow4") + Planet(2, "Venus", 8.9, "navajowhite") + Planet(3, "Earth", 9.8, "lightskyblue") + Planet(4, "Moon", 1.6, "gainsboro") + Planet(5, "Mars", 3.7, "orangered") + Planet(6, "Jupiter", 23.1, "olive") + Planet(7, "Saturn", 9, "burlywood") + Planet(8, "Uranus", 8.7, "cyan3") + Planet(9, "Neptune", 11, "dodgerblue") + Planet(10, "Pluto", 0.7, "rosybrown4") +] + + +framerate = 30 +height = 1000 # meters | also the video height + +frames = let + # Get planet with slowest acceleration + slowest = [p.gravity for p in planets] |> minimum + + # Kinematic equation to determine seconds to fall from height + time = 2 * height / slowest |> sqrt + + # Calculate total frames and add a few seconds at the end to display final result + ceil(Int, time * framerate) + framerate * 10 +end + +function ground(args...) + background("black") + sethue("white") +end + +font_height = 25 +width = 1500 + +# Give room for header and footer +top_padding = font_height * 3 +bottom_padding = font_height * 5 + 50 +total_height = height + top_padding + bottom_padding + +myvideo = Video(width, total_height) +Background(1:frames, ground) + +# Determine spacing and make some functions to help space the planets and text +spacing = width / (length(planets) + 1) +x_calc(planet::Planet) = (planet.position) * spacing - width / 2 + spacing / 2 +y_calc(planet::Planet) = -height / 2 + planet.radius +y_height(row) = total_height / 2 - font_height / 2 - font_height * row + +for planet in planets + + # Kinematic equations to calculate how many frames each planet will be active + t_final = 2 * (height - planet.radius * 2) / planet.gravity |> sqrt + v_final = planet.gravity * t_final + frame_final = ceil(Int, t_final * framerate) + + + + for f = 1:frame_final + + # Calculate time of current frame for kinematic math + time = f / framerate + + # Calculate planets current position + planet_y = 0.5 * planet.gravity * time^2 - height / 2 + + # Set the planets position + Object( + f:f, + JCircle(O, planet.radius, color = planet.color, action = :fill), + Point(x_calc(planet), planet_y + planet.radius), + ) + + # Update text for planets current state + Object( + f:f, + @JShape begin + fontsize(font_height) + text( + string(round((f - 1) / frames * framerate, digits = 1), "s"), + Point(x_calc(planet), y_height(1)), + halign = :center, + ) + text( + string(round(planet.gravity * time, digits = 2), "m/s"), + Point(x_calc(planet), y_height(0)), + halign = :center, + ) + end + ) + + # Leave a trail every few seconds to give an idea of the acceleration happening + if f % framerate * 4 == 0 + Object( + f:frames, + JCircle(O, planet.radius / 5, color = planet.color, action = :fill), + Point(x_calc(planet), planet_y), + ) + end + end + + # Make the planet sit at the bottom of the video for the rest of the frames + Object( + frame_final:frames, + JCircle(O, planet.radius, color = planet.color, action = :fill), + Point(x_calc(planet), height / 2 - planet.radius), + ) + + # Set all the text for after the planet is done moving + Object( + frame_final:frames, + @JShape begin + fontsize(font_height) + sethue("green") + text(planet.name, Point(x_calc(planet), y_height(3)), halign = :center) + text( + string(planet.gravity, "m/s^2"), + Point(x_calc(planet), y_height(2)), + halign = :center, + ) + + text( + string(round(t_final, digits = 1), "s"), + Point(x_calc(planet), y_height(1)), + halign = :center, + ) + text( + string(round(v_final, digits = 2), "m/s"), + Point(x_calc(planet), y_height(0)), + halign = :center, + ) + end + ) + + # Set text that is static during entire planet translation + Object( + 1:frame_final, + @JShape begin + fontsize(font_height) + text(planet.name, Point(x_calc(planet), y_height(3)), halign = :center) + text( + string(planet.gravity, "m/s^2"), + Point(x_calc(planet), y_height(2)), + halign = :center, + ) + end + ) + + + +end + + + +# Set the legend text +Object( + 1:frames, + @JShape begin + fontsize(font_height) + x_pt = -width / 2 + 10 + + text("1km", Point(x_pt, -height / 2 + font_height), halign = :left) + text("0km", Point(x_pt, height / 2), halign = :left) + + + fontsize(font_height * 0.75) + text("Planet:", Point(x_pt, y_height(3)), halign = :left) + text("Acceleration:", Point(x_pt, y_height(2)), halign = :left) + + text("Time:", Point(x_pt, y_height(1)), halign = :left) + text("Velocity:", Point(x_pt, y_height(0)), halign = :left) + + fontsize(font_height * 2) + sethue("royalblue") + text( + "Ball Falling 1km on Bodies in the Solar System", + Point(0, -height / 2 - font_height * 2), + halign = :center, + ) + end +) + + +render(myvideo; liveview = true) +# render(myvideo; pathname = "hacktober.gif") diff --git a/gravities.mp4 b/gravities.mp4 new file mode 100644 index 0000000..20b3ecb Binary files /dev/null and b/gravities.mp4 differ