0

Now that ggvoronoi package is not working anymore in R, I am using deldir to plot voronoi cells clipped by the convex hull for a bunch of points in the following way:

library(deldir)
set.seed(1)
x <- runif(50)
y <- runif(50)

tesselation <- deldir(x, y)
tiles <- tile.list(tesselation)

s <- seq(0, 2 * pi, length.out = 3000)
circle <- list(x = 0.5 * (1 + cos(s)),
               y = 0.5 * (1 + sin(s)))

plot(tiles, pch = 19,
     col.pts = "white",
     border = "white",
     fillcol = hcl.colors(50, "viridis"),
     clipp = circle)

enter image description here

I want to create a gradient plot for the tiles according to the area of the tiles. Or in some way to import tiles in ggplot and then use the functionalities like scale_fill_gradientn to achieve my goal. Can you please help me?

  • Could you make your example reproducible? I think you just need to add the construction of the `points` and `con.hull` variables and the `library()` calls for the functions you used. – user2554330 Aug 21 '22 at 19:59
  • I have added them as you requested. Thanks for your help :) Actually I need to color the cells according to `points$density_voronoi`, which is just 1/area for each cell. – Pratik Mullick Aug 21 '22 at 20:11
  • That's not reproducible without a lot of work. Follow the suggestions at https://stackoverflow.com/q/5963269/2554330 if you want someone to help you. – user2554330 Aug 21 '22 at 20:19
  • I apologize. I have now summarized the problem with a simple example. Thanks for your patience :) – Pratik Mullick Aug 21 '22 at 20:26

1 Answers1

1

Thanks for your nice reproducible example.

As far as I know, ggplot2 doesn't support clipping polygons directly. There are some workarounds: drawing a big polygon on top of them to obscure the parts you don't want to see, or clipping the polygons before you draw them using some other package, or working "down a level" with the grid package to modify the final plot. This question has answers that explore a couple of those methods. Here, I'm just going to concentrate on drawing the Voronoi cells and not attempt the clipping.

The main issue is extracting the cells and their color from the tiles object. It's a list, with one entry per cell. If you look at str(tiles[[1]]) you'll see something like this:

List of 6
 $ ptNum: int 1
 $ pt   : Named num [1:2] 0.266 0.478
  ..- attr(*, "names")= chr [1:2] "x" "y"
 $ x    : num [1:8] 0.386 0.365 0.317 0.128 0.141 ...
 $ y    : num [1:8] 0.638 0.656 0.67 0.642 0.509 ...
 $ bp   : logi [1:8] FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ area : num 0.0402
 - attr(*, "ncomp")= num 1

The boundary of the cell is in the polygon defined by the x and y components.

So here's one way to do what you want (except for the clipping):

library(ggplot2)
library(deldir)

set.seed(1)
x <- runif(50)
y <- runif(50)

tesselation <- deldir(x, y)
tiles <- tile.list(tesselation)

s <- seq(0, 2 * pi, length.out = 3000)
circle <- list(x = 0.5 * (1 + cos(s)),
               y = 0.5 * (1 + sin(s)))

points <- data.frame(x=x, y=y)
colors <- hcl.colors(50, "viridis")

g <- ggplot(points, aes(x = x, y = y))
for (i in 1:50)
  g <- g + geom_polygon(data = data.frame(x = tiles[[i]]$x,
                                          y = tiles[[i]]$y,
                                          density = 1/tiles[[i]]$area), 
                        aes(fill = density))
g <- g + geom_point(col = "white")
g

Created on 2022-08-22 with reprex v2.0.2

user2554330
  • 37,248
  • 4
  • 43
  • 90