Transforms latitude/longitude/altitude coordinates to the reference system used in `render_highquality()`, so they can be used to create high quality pathtraced animations by passing the output to the `animation_camera_coords` argument in `render_highquality()`.

This function converts the path values to rayshader coordinates (by setting `return_coords = TRUE` in `render_path()`) and then subtracts out the rgl y-offset, which can be obtained by calling the internal function `rayshader:::get_scene_depth()`.

convert_path_to_animation_coords(
  lat,
  long = NULL,
  altitude = NULL,
  extent = NULL,
  frames = 360,
  reorder = FALSE,
  reorder_first_index = 1,
  reorder_duplicate_tolerance = 0.1,
  reorder_merge_tolerance = 1,
  simplify_tolerance = 0,
  zscale = 1,
  heightmap = NULL,
  offset = 5,
  type = "bezier",
  offset_lookat = 1,
  constant_step = TRUE,
  curvature_adjust = "none",
  curvature_scale = 30,
  follow_camera = FALSE,
  follow_distance = 100,
  follow_angle = 45,
  follow_rotations = 0,
  follow_fixed = FALSE,
  follow_fixed_offset = c(10, 10, 10),
  damp_motion = FALSE,
  damp_magnitude = 0.1,
  resample_path_evenly = TRUE,
  ...
)

Arguments

lat

Vector of latitudes (or other coordinate in the same coordinate reference system as extent).

long

Vector of longitudes (or other coordinate in the same coordinate reference system as extent).

altitude

Elevation of each point, in units of the elevation matrix (scaled by zscale). If left `NULL`, this will be just the elevation value at ths surface, offset by `offset`. If a single value, all data will be rendered at that altitude.

extent

Either an object representing the spatial extent of the scene (either from the `raster`, `terra`, `sf`, or `sp` packages), a length-4 numeric vector specifying `c("xmin", "xmax","ymin","ymax")`, or the spatial object (from the previously aforementioned packages) which will be automatically converted to an extent object.

frames

Default `360`. Total number of animation frames.

reorder

Default `TRUE`. If `TRUE`, this will attempt to re-order the rows within an `sf` object with multiple paths to be one continuous, end-to-end path. This happens in two steps: merging duplicate paths that have end points that match with another object (within `reorder_duplicate_tolerance` distance), and then merges them (within `reorder_merge_tolerance` distance) to form a continuous path.

reorder_first_index

Default `1`. The index (row) of the `sf` object in which to begin the reordering process. This merges and reorders paths within `reorder_merge_tolerance` distance until it cannot merge any more, and then repeats the process in the opposite direction.

reorder_duplicate_tolerance

Default `0.1`. Lines that have start and end points (does not matter which) within this tolerance that match a line already processed (order determined by `reorder_first_index`) will be discarded.

reorder_merge_tolerance

Default `1`. Lines that have start points that are within this distance to a previously processed line's end point (order determined by `reorder_first_index`) will be reordered within the `sf` object to form a continuous, end-to-end path.

simplify_tolerance

Default `0` (no simplification). If greater than zero, simplifies the path to the tolerance specified. This happens after the data has been merged if `reorder = TRUE`. If the input data is specified with long-lat coordinates and `sf_use_s2()` returns `TRUE`, then the value of simplify_tolerance must be specified in meters.

zscale

Default `1`. The ratio between the x and y spacing (which are assumed to be equal) and the z axis in the original heightmap.

heightmap

Default `NULL`. Automatically extracted from the rgl window--only use if auto-extraction of matrix extent isn't working. A two-dimensional matrix, where each entry in the matrix is the elevation at that point. All points are assumed to be evenly spaced.

offset

Default `5`. Offset of the track from the surface, if `altitude = NULL`.

type

Default `cubic`. Type of transition between keyframes. Other options are `linear`, `quad`, `bezier`, `exp`, and `manual`. `manual` just returns the values passed in, properly formatted to be passed to `render_animation()`.

offset_lookat

Default `0`. Amount to offset the lookat position, either along the path (if `constant_step = TRUE`) or towards the derivative of the Bezier curve.

constant_step

Default `TRUE`. This will make the camera travel at a constant speed.

curvature_adjust

Default `none`. Other options are `position`, `lookat`, and `both`. Whether to slow down the camera at areas of high curvature to prevent fast swings. Only used for curve `type = bezier`. This does not preserve key frame positions. Note: This feature will likely result in the `lookat` and `position` diverging if they do not have similar curvatures at each point. This feature is best used when passing the same set of points to `positions` and `lookats` and providing an `offset_lookat` value, which ensures the curvature will be the same.

curvature_scale

Default `30`. Constant dividing factor for curvature. Higher values will subdivide the path more, potentially finding a smoother path, but increasing the calculation time. Only used for curve `type = bezier`. Increasing this value after a certain point will not increase the quality of the path, but it is scene-dependent.

follow_camera

Default `FALSE`. If `TRUE`, this generates a 3rd person view that follows the path specified in `lat`, `long`, and `altitude`. The distance to the camera is specified by `follow_distance`, and the angle (off the ground) is specified by `follow_angle`. Make the camera rotate around the point as it moves by setting `follow_rotations` to a non-zero number. The camera points in the direction of the You can also set the camera to be a fixed distance and angle above the by settings `follow_fixed = TRUE` and specifying the distance in `follow_fixed_offset`.

follow_distance

Default `100`. Distance for the camera to follow the point when `follow_camera = TRUE`.

follow_angle

Default `45`. Angle (off the ground) of the camera when `follow_camera = TRUE`.

follow_rotations

Default `0`. Number of rotations around the point when `follow_camera = TRUE`.

follow_fixed

Default `FALSE`. If `TRUE`, the camera doesn't look in the direction of the path, but rather sits at a fixed relative location to the path.

follow_fixed_offset

Default `c(10,10,10)`. If `follow_fixed = TRUE`, the offset from the path to place the camera.

damp_motion

Default `FALSE`. Whether the suppress quick, jerky movements of the camera by linearly interpolating between the current camera position and the goal position. Amount of linear interpolation set in `damp_magnitude`.

damp_magnitude

Default `0.1`. Amount of linear interpolation if `damp_motion = TRUE`.

resample_path_evenly

Default `TRUE`. This re-samples points along the path so that the camera moves at a constant speed along the path. This also allows paths with large numbers of points to be used with a smaller number of frames, and improves computation time of the animation path in those instances.

...

Other arguments to pass to `rayrender::generate_camera_motion()`

Examples

#Generate a circle in Monterey Bay and fly around on top of it
if(run_documentation()) {
montereybay %>%
 sphere_shade() %>%
 plot_3d(montereybay,zscale=50,water=TRUE,
         shadowcolor="#40310a", background = "tan",
         theta=210,  phi=22, zoom=0.40, fov=55)
         
moss_landing_coord = c(36.806807, -121.793332)
t = seq(0,2*pi,length.out=1000)
circle_coords_lat = moss_landing_coord[1] + 0.25 * sin(t)
circle_coords_long = moss_landing_coord[2] + 0.25  *  cos(t)
render_path(extent = attr(montereybay,"extent"), heightmap = montereybay,
           lat = unlist(circle_coords_lat), long = unlist(circle_coords_long),
           zscale=50, color="red", antialias=TRUE,
           offset=100, linewidth=2)
render_snapshot()

camera_path = convert_path_to_animation_coords(extent = attr(montereybay,"extent"), 
                                              heightmap = montereybay,
                                              lat = unlist(circle_coords_lat), 
                                              long = unlist(circle_coords_long),
                                              fovs = 80,
                                              zscale=50, offset=250, frames = 25)

#Render a series of frames, following the path specified above
temp_dir = tempdir()
render_highquality(samples=16, animation_camera_coords = camera_path, 
                  width=200,height=200, filename = sprintf("%s/frame",temp_dir),
                  use_extruded_paths = TRUE,
                  sample_method="sobol_blue")

#Plot all these frames
image_list = list()
for(i in 1:25) {
  image_list[[i]] = png::readPNG(sprintf("%s/frame%d.png",temp_dir,i))
}
rayimage::plot_image_grid(image_list, dim = c(5,5))
}
#> Error: Index out of bounds: [index=5; extent=5].


if(run_documentation()) {
#Now render a third-person view by setting `follow_camera = TRUE`
camera_path = convert_path_to_animation_coords(extent = attr(montereybay,"extent"), 
                                              heightmap = montereybay,
                                              lat = unlist(circle_coords_lat), 
                                              long = unlist(circle_coords_long),
                                              fovs = 80,
                                              follow_camera = TRUE,
                                              zscale=50, offset=250, frames = 25)

#Render a series of frames, following the path specified above
temp_dir = tempdir()
render_highquality(samples=16, animation_camera_coords = camera_path, 
                  width=200,height=200, filename = sprintf("%s/frame",temp_dir),
                  use_extruded_paths = TRUE,
                  sample_method="sobol_blue")

#Plot all these frames
image_list = list()
for(i in 1:25) {
  image_list[[i]] = png::readPNG(sprintf("%s/frame%d.png",temp_dir,i))
}
rayimage::plot_image_grid(image_list, dim = c(5,5))
}
#> Error: Index out of bounds: [index=5; extent=5].