--- title: "Custom Visualization with ggplot2 and plotly" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Custom Visualization with ggplot2 and plotly} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5 ) ``` ```{r} library(orbitr) ``` `plot_orbits()` and `plot_orbits_3d()` are convenience functions for quick trajectory plots — they're designed to get you a useful visualization in one line so you can focus on setting up the physics. But the real power of `orbitr` is that `simulate_system()` returns a standard tidy tibble. You can use `ggplot2`, `plotly`, or any other visualization tool directly on the output. ## The Raw Output Here's what the simulation tibble looks like: ```{r} sim <- create_system() |> add_body("Earth", mass = mass_earth) |> add_body("Moon", mass = mass_moon, x = distance_earth_moon, vy = speed_moon) |> simulate_system(time_step = seconds_per_hour, duration = seconds_per_day * 28) sim ``` Each row is one body at one point in time. Every column is available for plotting, filtering, or analysis. Since this is just a tibble, you have the full power of `dplyr` and `ggplot2` at your disposal. ## Custom ggplot2 Visualizations For example, in the Earth-Moon system, `plot_orbits()` shows overlapping circles because both bodies orbit their shared barycenter at roughly the same scale. A more useful visualization might plot each body's distance from the barycenter over time: ```{r} library(ggplot2) sim |> dplyr::mutate(r = sqrt(x^2 + y^2)) |> ggplot(aes(x = time / seconds_per_day, y = r, color = id)) + geom_line(linewidth = 1) + labs( title = "Distance from Barycenter Over Time", x = "Time (days)", y = "Distance (m)", color = "Body" ) + theme_minimal() ``` Or plot the Moon's path relative to Earth with a color gradient showing the passage of time: ```{r} sim |> shift_reference_frame("Earth", keep_center = FALSE) |> ggplot(aes(x = x, y = y, color = time / seconds_per_day)) + geom_path(linewidth = 1.2) + scale_color_viridis_c(name = "Day") + coord_equal() + labs(title = "Lunar Orbit (Earth-Centered)", x = "X (m)", y = "Y (m)") + theme_minimal() ``` ## Custom plotly Visualizations Just as `plot_orbits()` is a quick convenience for 2D work, `plot_orbits_3d()` is a quick convenience for 3D. Both are intentionally simple — they get you a useful plot in one line so you can focus on the physics, not the formatting. When you need more control, the simulation tibble works just as well with `plotly` as it does with `ggplot2`. For example, you could color trajectories by speed rather than by body: ```{r} library(plotly) sim <- create_system() |> add_body("Earth", mass = mass_earth) |> add_body("Moon", mass = mass_moon, x = distance_earth_moon, vy = speed_moon * cos(5 * pi / 180), vz = speed_moon * sin(5 * pi / 180)) |> simulate_system(time_step = seconds_per_hour, duration = seconds_per_day * 28) sim <- sim |> dplyr::mutate(speed = sqrt(vx^2 + vy^2 + vz^2)) plot_ly() |> add_trace( data = dplyr::filter(sim, id == "Moon"), x = ~x, y = ~y, z = ~z, type = 'scatter3d', mode = 'lines', line = list( width = 5, color = ~speed, colorscale = 'Viridis', showscale = TRUE, colorbar = list(title = "Speed (m/s)") ), name = "Moon" ) |> add_trace( data = dplyr::filter(sim, id == "Earth"), x = ~x, y = ~y, z = ~z, type = 'scatter3d', mode = 'lines', line = list(width = 3, color = 'gray'), name = "Earth" ) |> layout( title = "Lunar Orbit Around Earth", showlegend = FALSE, scene = list( xaxis = list(title = 'X (m)'), yaxis = list(title = 'Y (m)'), zaxis = list(title = 'Z (m)'), aspectmode = "data" ) ) ``` The point is the same as with `ggplot2`: `simulate_system()` returns a standard tibble, so you have full access to `plotly`'s API for anything the built-in plotting functions don't cover.