Skip to contents

Setup

Packages

Base Plot

To avoid repetitive code, we make a base plot:

#| label: baseplot

my_font <- "Roboto Condensed"
my_font_size <- 20
my_point_size <- 2
my_arrowhead <- arrowheadr::arrow_head_deltoid(2.1)

# my_colors <- viridis::viridis(2, begin = .25, end = .5)
my_colors <- c("#3B528B", "#21908C")

theme_set(
  theme_minimal(
    base_size = my_font_size,
    base_family = my_font) +
    theme(axis.title.y = element_text(angle = 0, vjust = 0.5)))

bp <- ggdiagram(
  font_family = my_font,
  font_size = my_font_size,
  point_size = my_point_size,
  linewidth = .5,
  theme_function = theme_minimal,
  axis.title.x =  element_text(face = "italic"),
  axis.title.y = element_text(
    face = "italic",
    angle = 0,
    hjust = .5,
    vjust = .5)) +
  scale_x_continuous(labels = WJSmisc::signs_centered,
                     limits = c(-4, 4)) +
  scale_y_continuous(labels = signs::signs,
                     limits = c(-4, 4))

Specifying a Circle

Circles can be specified by a point at the circle’s center (x0, y0) and a radius r (the distance from the center to the circle’s edge).

(xx0)2+(yy0)2=r2 (x-x_0)^2+(y-y_0)^2=r^2

p <- ob_point(0,0)
r <- 3
c1 <-  ob_circle(center = p, radius = 3)
c1
#> <ob_circle>
#> @ center: <ob_point>
#>  @ x: num 0
#>  @ y: num 0
#> @ radius: num 3
#> Other props: label, alpha, color, fill, linewidth, linetype, n,
#>              area, bounding_box, circumference, diameter, length,
#>              polygon, style, tibble, geom, angle_at, normal_at,
#>              tangent_at, point_at, aesthetics
Code
bp +
  c1 +
  ob_segment(
    c1@center,
    c1@point_at(0),
    color = my_colors[1],
    label = ob_label(paste0("*r* = ", c1@radius), angle = 0, vjust = 0)
  ) +
  c1@center@label(vjust = 1.2, plot_point = T) 
Figure 1: A circle can be specified with a center and a radius,

Point on the circle at a specific angle

c1@point_at(degree(60))
#> <ob_polar>
#> @ x    : num 1.5
#> @ y    : num 2.6
#> @ r    : num 3
#> @ theta: <radian>
#>  @ radian: num 1.05
#> Other props: alpha, color, fill, shape, size, stroke, auto_label,
#>              bounding_box, length, style, tibble, xy, geom, label,
#>              aesthetics
Code
deg <- degree(60)

bp + 
  c1 +
  {p45 <- c1@point_at(deg)} +
  p45@label(polar_just = ob_polar(deg, 1.5)) +
  ob_segment(c1@center, p45) +
  ob_arc(radius = 1, start = degree(0), end = deg, label = deg)
Figure 2: Point on ellipse that is 45° from the x-axis.

Placing circles

Placing circles next to each other

The place function places an object at a specified direction and distance from another object.

bp + 
  {A <- ob_circle(
    center = ob_point(-2, 0), 
    radius = 1, 
    label = ob_label("A", size = 30))} + 
  place(
    ob_circle(radius = 1.5,
           label = ob_label("B", size = 30)),
    from = A,
    where = "right",
    sep = 1)
Figure 3: Place Circle B one unit to the right of Circle A

The where argument can take degrees or named positions:

east, east-northeast, northeast, north-northeast, north, north-northwest, northwest, west-northwest, west, west-southwest, southwest, south-southwest, south, south-southeast, southeast, east-southeast, right, top right, top, top left, left, bottom left, bottom, bottom right, below, above

Multiple circles can be created at once with named directions:

bp + 
  {c3 <- ob_circle(ob_point(0, 0), radius = 1)} + 
  place(ob_circle(radius = .5), 
        from = c3, 
        where = c("northwest", 
                  "northeast", 
                  "south-southeast", 
                  "south-southwest"), 
        sep = 1)
Figure 4: Place mutliple circles using named directions

Or with numbers (degrees):

bp + 
  c3 + 
  place(ob_circle(radius = .5), 
        from = c3, 
        where = c(0, 30, -30), 
        sep = 1)
Figure 5: Place mutliple circles using degrees

With styles:

bp +
  {c4 <- ob_circle(
      radius = 1,
      color = NA,
      fill = "gray35")} +
  place(
    ob_circle(
      color = NA,
      fill = class_color(viridis::viridis(
        n = 6, 
        option = "D"))@lighten(.7)@color
    ),
    from = c4,
    where = degree(seq(0, 300, 60)),
    sep = 1
  ) 
Figure 6: Place mutliple circles with styling

Placing circles next to points and points next to circles

This works the same as placing circles next to each other. Here we create a point in the center, place six circles around it, and then place 12 points around each circle.

bp + 
  {p1 <- ob_point(0,0)} +
  {c6 <- place(x = ob_circle(radius = .5, 
                          fill = viridis::viridis(6), 
                          color = NA), 
        from = p1, 
        where = degree(seq(0,300,60)), 
        sep = 2)} +
  purrr::map(as.list(c6), 
             \(x) ob_point(color = x@fill) |> 
               place(from = x, 
                     where = degree(seq(0, 330, 30)), 
                     sep = .5) |> 
               as.geom())
Figure 7: Place circles around a point, and points around each circle

Placing lines next to circles

bp +
  {c7 <- ob_circle()} +
  place(ob_line(), c7, where = degree(45), sep = 1)
Figure 8: Placing a line one unit northeast of a circle

Drawing path connectors between circles

Let’s make two circles and draw an arrow path between them

bp + 
  {c1 <- ob_circle(ob_point(-2, 2), radius = 1)} + 
  {c2 <- ob_circle(ob_point(1.5,-1.5), radius = 1.5)} +
  connect(c1, c2)
Figure 9: Connect two circles

That is fine, but we often need labels and styling to make scientific diagrams. For example:

bp +
  {cthis <- ob_circle(
    ob_point(-2, 2),
    radius = 1,
    fill = my_colors[1],
    color = NA,
    label = ob_label(
      "This",
      color = "white",
      fill = NA,
      size = 35
    )
  )} + 
  {cthat <- ob_circle(
    ob_point(1.5, -1.5),
    radius = 1.5,
    fill = my_colors[2],
    color = NA,
    label = ob_label(
      "That",
      color = "white",
      fill = NA,
      size = 55
    )
  )} +
  connect(cthis, cthat, 
       resect = 2, 
       label = ob_label("Causes", size = 20, vjust = 0),
       color = "black")
Figure 10: Connect two circles with labels and styles

Paths between circles and lines

bp + 
  c1 +
  {l1 <- ob_line(slope = 2, intercept = 0)} +
  connect(c1, l1) +
  {c2 <- ob_circle(ob_point(2, -2))} + 
  connect(l1, c2)
Figure 11: Connect a circle to a line and a line to a circle