---
title: "Photography calculations"
---


```{r}
#| label: setup
library(tidyverse)
library(gt)

coc_fx <- 0.025
coc_dx <- 0.020
apertures <- c(2.0, 2.8, 4, 5.6, 8)
distances <- c(2, 4, 6, 8, 10) # meters

# Source of equations: https://dofmaster.com/equations.html

# Returns the hyperfocal distance in millimeters given a focal length in mm,
# an aperture, and a circle of confucion (CoC)
hyperfocal_distance <- function(focal_length, aperture, circle_of_confusion) {
  focal_length^2 / (aperture * circle_of_confusion) + focal_length
}

# Returns the near focus limit in millimeters given a focal length in mm,
# a distance in mm, and a hyperfocal distance in mm
near_focus <- function(focal_length, distance, hyperfocal_distance) {
  (hyperfocal_distance - focal_length) * distance / (hyperfocal_distance + distance - 2 * focal_length)
}

# Returns the far focus limit in millimeters given a focal length in mm,
# a distance in mm, and a hyperfocal distance in mm
far_focus <- function(focal_length, distance, hyperfocal_distance) {
  (hyperfocal_distance - focal_length) * distance / (hyperfocal_distance - distance)
}

# Returns the depth of field in millimeters given a focal length of the lens,
# an aperture, a distance of the focused object, and a circle of confusion.
# All distances in millimeters.
depth_of_field <- function(focal_length, aperture, distance, circle_of_confusion) {
  h <- hyperfocal_distance(focal_length, aperture, circle_of_confusion)
  ff <- far_focus(focal_length, distance, h)
  nf <- near_focus(focal_length, distance, h)
  dof <- ff - nf
  ifelse(dof >= 0, dof, Inf)
}
```

# Full frame with tele lens 150 mm

```{r}
#| label: tele_lens
expand_grid(aperture = apertures, distance = distances) |> 
  mutate(dof = round(depth_of_field(150, aperture, distance * 1000, coc_fx) / 10, 1)) |> 
  pivot_wider(names_from = distance, values_from = dof) |> 
  gt() |> 
  tab_spanner("Object distance (m)", columns = -aperture) |> 
  cols_label(aperture = "F") |> 
  tab_header(
    title = "Depth of field in centimeters",
    subtitle = "full frame, 150 mm focal length"
  )
```

# Full frame with wide-angle lens 20 mm

```{r}
#| label: wide_angle
expand_grid(aperture = apertures, distance = distances) |> 
  mutate(dof = round(depth_of_field(20, aperture, distance * 1000, coc_fx) / 10, 1)) |> 
  pivot_wider(names_from = distance, values_from = dof) |> 
  gt() |> 
  tab_spanner("Object distance (m)", columns = -aperture) |> 
  cols_label(aperture = "F") |> 
  tab_header(
    title = "Depth of field in centimeters",
    subtitle = "full frame, 20 mm focal length"
  )
```
