---
title: "3D Plotting"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{3D Plotting}
  %\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)
```

All simulations in `orbitr` run in full 3D — every body always has `x`, `y`, and `z` coordinates. When all motion happens in the XY plane (i.e., `z = 0` and `vz = 0` for every body), `plot_orbits()` produces a static 2D `ggplot2` chart. The moment any body has non-zero Z motion, `plot_orbits()` automatically switches to an interactive 3D `plotly` visualization — no code changes needed.

You can also force 3D rendering for planar data with `three_d = TRUE`, which can be useful if you want the interactive rotation and zoom capabilities even for a flat system.

## How the 2D/3D Dispatch Works

`plot_orbits()` checks whether `any(sim_data$z != 0)`. If there's any Z-axis movement — or if you pass `three_d = TRUE` — it hands off to `plot_orbits_3d()`, which uses `plotly` for interactive 3D rendering. Otherwise it falls back to a static `ggplot2` chart.

If `plotly` isn't installed, the function warns you and falls back to the 2D plot even for 3D data.

## A Tilted Lunar Orbit

The Moon's real orbit is inclined about 5° to the ecliptic. You can approximate this by giving the Moon a small `vz` component:

```{r}
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) |>
  plot_orbits()
```

Because `vz` is non-zero, `plot_orbits()` detects 3D motion and returns an interactive plotly widget. You can drag to rotate, scroll to zoom, and hover to see timestamps.

## Forcing 3D for Flat Data

Even if your system is entirely planar, you can opt into the interactive 3D viewer:

```{r}
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) |>
  plot_orbits(three_d = TRUE)
```

This gives you the same rotation and zoom controls, even though all the Z values are zero.
