rotate_3d {rearrr}R Documentation

Rotate the values around an origin in 3 dimensions

Description

[Experimental]

The values are rotated counterclockwise around a specified origin.

The origin can be supplied as coordinates or as a function that returns coordinates. The latter can be useful when supplying a grouped data.frame and rotating around e.g. the centroid of each group.

Usage

rotate_3d(
  data,
  x_col,
  y_col,
  z_col,
  x_deg = 0,
  y_deg = 0,
  z_deg = 0,
  suffix = "_rotated",
  origin = NULL,
  origin_fn = NULL,
  keep_original = TRUE,
  degrees_col_name = ".degrees",
  origin_col_name = ".origin",
  overwrite = FALSE
)

Arguments

data

data.frame or vector.

x_col, y_col, z_col

Name of x/y/z column in `data`. All must be specified.

x_deg, y_deg, z_deg

Degrees to rotate values around the x/y/z-axis counterclockwise. In [-360, 360]. Can be vectors with multiple degrees.

`x_deg` is roll. `y_deg` is pitch. `z_deg` is yaw.

suffix

Suffix to add to the names of the generated columns.

Use an empty string (i.e. "") to overwrite the original columns.

origin

Coordinates of the origin to rotate around. Vector with 3 elements (i.e. origin_x, origin_y, origin_z). Ignored when `origin_fn` is not NULL.

origin_fn

Function for finding the origin coordinates.

Input: Each column will be passed as a vector in the order of `cols`.

Output: A vector with one scalar per dimension.

Can be created with create_origin_fn() if you want to apply the same function to each dimension.

E.g. `create_origin_fn(median)` would find the median of each column.

Built-in functions are centroid(), most_centered(), and midrange()

keep_original

Whether to keep the original columns. (Logical)

Some columns may have been overwritten, in which case only the newest versions are returned.

degrees_col_name

Name of new column with the degrees. If NULL, no column is added.

Also adds a string version with the same name + "_str", making it easier to group by the degrees when plotting multiple rotations.

origin_col_name

Name of new column with the origin coordinates. If NULL, no column is added.

overwrite

Whether to allow overwriting of existing columns. (Logical)

Details

Applies the following rotation matrix:

[ cos \alpha cos \beta , cos \alpha sin \beta sin \gamma - sin \alpha cos \gamma , cos \alpha sin \beta cos \gamma + sin \alpha sin \gamma ]
[ sin \alpha cos \beta , sin \alpha sin \beta sin \gamma + cos \alpha cos \gamma , sin \alpha sin \beta cos \gamma - cos \alpha sin \gamma ]
[ -sin \beta , cos \beta sin \gamma , cos \beta cos \gamma ]

Where \alpha = `z_deg` in radians, \beta = `y_deg` in radians, \gamma = `x_deg` in radians.

As specified at Wikipedia/Rotation_matrix.

Value

data.frame (tibble) with six new columns containing the rotated x-,y- and z-values and the degrees and origin coordinates.

Author(s)

Ludvig Renbo Olsen, r-pkgs@ludvigolsen.dk

See Also

Other mutate functions: apply_transformation_matrix(), cluster_groups(), dim_values(), expand_distances(), expand_distances_each(), flip_values(), roll_values(), rotate_2d(), shear_2d(), shear_3d(), swirl_2d(), swirl_3d()

Other rotation functions: rotate_2d(), swirl_2d(), swirl_3d()

Examples

# Attach packages
library(rearrr)
library(dplyr)
has_ggplot <- require(ggplot2)  # Attach if installed

# Set seed
set.seed(3)

# Create a data frame
df <- data.frame(
  "x" = 1:12,
  "y" = c(1:4, 9:12, 15:18),
  "z" = runif(12),
  "g" = rep(1:3, each = 4)
)

# Rotate values 45 degrees around x-axis at (0, 0, 0)
rotate_3d(df, x_col = "x", y_col = "y", z_col = "z", x_deg = 45, origin = c(0, 0, 0))

# Rotate all axes around the centroid
df_rotated <- df %>%
  rotate_3d(
    x_col = "x",
    y_col = "y",
    z_col = "z",
    x_deg = c(0, 72, 144, 216, 288),
    y_deg = c(0, 72, 144, 216, 288),
    z_deg = c(0, 72, 144, 216, 288),
    origin_fn = centroid
  )
df_rotated

# Plot rotations
if (has_ggplot){
  ggplot(df_rotated, aes(x = x_rotated, y = y_rotated, color = .degrees_str, alpha = z_rotated)) +
    geom_vline(xintercept = mean(df$x), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_hline(yintercept = mean(df$y), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_line(alpha = .4) +
    geom_point() +
    theme_minimal() +
    labs(x = "x", y = "y", color = "degrees", alpha = "z (opacity)")
}

## Not run: 
# Plot 3d with plotly
plotly::plot_ly(
  x = df_rotated$x_rotated,
  y = df_rotated$y_rotated,
  z = df_rotated$z_rotated,
  type = "scatter3d",
  mode = "markers",
  color = df_rotated$.degrees_str
)

## End(Not run)


# Rotate randomly around all axes
df_rotated <- df %>%
  rotate_3d(
    x_col = "x",
    y_col = "y",
    z_col = "z",
    x_deg = round(runif(10, min = 0, max = 360)),
    y_deg = round(runif(10, min = 0, max = 360)),
    z_deg = round(runif(10, min = 0, max = 360)),
    origin_fn = centroid
  )
df_rotated

# Plot rotations
if (has_ggplot){
  ggplot(df_rotated, aes(x = x_rotated, y = y_rotated, color = .degrees_str, alpha = z_rotated)) +
    geom_vline(xintercept = mean(df$x), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_hline(yintercept = mean(df$y), size = 0.2, alpha = .4, linetype = "dashed") +
    geom_line(alpha = .4) +
    geom_point() +
    theme_minimal() +
    labs(x = "x", y = "y", color = "degrees", alpha = "z (opacity)")
}

## Not run: 
# Plot 3d with plotly
plotly::plot_ly(
  x = df_rotated$x_rotated,
  y = df_rotated$y_rotated,
  z = df_rotated$z_rotated,
  type = "scatter3d",
  mode = "markers",
  color = df_rotated$.degrees_str
)

## End(Not run)


# Rotate around group centroids
df_grouped <- df %>%
  dplyr::group_by(g) %>%
  rotate_3d(
    x_col = "x",
    y_col = "y",
    z_col = "z",
    x_deg = c(0, 72, 144, 216, 288),
    y_deg = c(0, 72, 144, 216, 288),
    z_deg = c(0, 72, 144, 216, 288),
    origin_fn = centroid
  )

# Plot A and A rotated around group centroids
if (has_ggplot){
  ggplot(df_grouped, aes(x = x_rotated, y = y_rotated, color = .degrees_str, alpha = z_rotated)) +
    geom_point() +
    theme_minimal() +
    labs(x = "x", y = "y", color = "degrees", alpha = "z (opacity)")
}

## Not run: 
# Plot 3d with plotly
plotly::plot_ly(
  x = df_grouped$x_rotated,
  y = df_grouped$y_rotated,
  z = df_grouped$z_rotated,
  type = "scatter3d",
  mode = "markers",
  color = df_grouped$.degrees_str
)

## End(Not run)

[Package rearrr version 0.3.4 Index]