Intro Thoughts

Status Quo

library(tidyverse)

Experiment

library(tidyverse)
tibble(x = runif(50),
       y = runif(50)) |>
  ggplot() +
  aes(x = x, y = y) +
  ggforce::geom_voronoi_tile() +
  geom_point()

layer_data(i = 1) |> head()
##   group        x        y    theta     orig_x    orig_y PANEL colour      fill
## 1  1:-1 0.112614 0.786635 1.018779 0.05260938 0.6892061     1     NA #333333FF
## 2  1:-1 0.053710 0.796997 1.560582 0.05260938 0.6892061     1     NA #333333FF
## 3  1:-1 0.044423 0.632866 4.568102 0.05260938 0.6892061     1     NA #333333FF
## 4  1:-1 0.085623 0.641826 5.320959 0.05260938 0.6892061     1     NA #333333FF
## 5  1:-1 0.133893 0.674931 6.109339 0.05260938 0.6892061     1     NA #333333FF
## 6  2:-1 0.773546 1.087819 2.095932 0.84756837 0.9600634     1     NA #333333FF
##   linewidth linetype alpha
## 1       0.5        1    NA
## 2       0.5        1    NA
## 3       0.5        1    NA
## 4       0.5        1    NA
## 5       0.5        1    NA
## 6       0.5        1    NA

five-ish from TVDB

library(igraph)
## 
## Attaching package: 'igraph'
## The following objects are masked from 'package:lubridate':
## 
##     %--%, union
## The following objects are masked from 'package:dplyr':
## 
##     as_data_frame, groups, union
## The following objects are masked from 'package:purrr':
## 
##     compose, simplify
## The following object is masked from 'package:tidyr':
## 
##     crossing
## The following object is masked from 'package:tibble':
## 
##     as_data_frame
## The following objects are masked from 'package:stats':
## 
##     decompose, spectrum
## The following object is masked from 'package:base':
## 
##     union
# Init data
df <- tibble(x = runif(50), y = runif(50))

# Make a graph of delaunay triangulation of the points
delaunay <- deldir::deldir(df$x, df$y)$delsgs
delaunay <- cbind(delaunay$ind1, delaunay$ind2)
g <- igraph::graph_from_edgelist(delaunay, directed = FALSE)

# For every vertex, search an unused colour
for (v in seq_along(V(g))) {
  v <- V(g)[v] # Index to current vertex
  nn <- ego(g, nodes = v)[[1]] # Current vertex to neighbours
  
  # Determine which colours are already in use
  nn_colours <- vertex_attr(g, "colour", index = nn) %||% 0
  nn_colours <- unique(nn_colours[!is.na(nn_colours)])
  if (length(nn_colours) == 0) {
    nn_colours <- 0
  }
  mx <- max(nn_colours)
  
  if (mx == 0) { # When no colours have been assigned to neighbours
    i <- 1L
  } else {
    # Try to find lowest colour that isn't in use by neighbours
    i <- setdiff(seq_len(mx), nn_colours)
    if (length(i) > 0) {
      i <- i[1]
    } else {
      i <- mx + 1 # If not found, increase local maximum
    }
  }
  g <- set_vertex_attr(g, "colour", index = v, value = i)
}

df$colour <- vertex_attr(g, "colour")

ggplot(df) +
  aes(x = x, y = y) +
  ggforce::geom_voronoi_tile(aes(fill = factor(colour), group = 1)) +
  geom_point()

ggplot(df) +
  aes(x = x, y = y, color = factor(colour)) +
  geom_point() + 
  scale_color_viridis_d()

Closing remarks, Other Relevant Work, Caveats