1

I have a Delaunay triangulation in a polygon with a hole (a so-called constrained Delaunay triangulation):

enter image description here

I'm able to construct the Voronoi cells by the duality principle. But some of them go outside the polygon (they go in the hole or outside the big perimeter):

enter image description here

How could I clip the Voronoi cells to the boundary of the big polygon? Maybe with the sf package, but I never used it.

(NB: the two pictures do not have the same scale.)


Edit

No sorry, that's not correct. Here is the picture with the Voronoi cells to which I added the big polygon:

enter image description here

So in fact I discarded the cells that go outside the polygon.

Will see if I can I change that but probably I will delete this question (and perhaps open a new one).

Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225

1 Answers1

0

With {sf} you could try along the exemplary lines below. A polygon with hole can be used for clipping, too.

library(sf)

the_points <- st_multipoint(cbind(rnorm(10), rnorm(10))) 

the_voronoi <- 
  the_points |> 
  st_voronoi() |>
  st_geometry() |> 
  lapply(FUN = `[`) |>
  lapply(FUN = st_multipolygon) |>
  st_as_sfc() |>
  st_cast('POLYGON')

## create a polygon with hole(s) by supplying a list of
## matrices, all after the first matrix defining the holes:
the_clip_with_hole <- 
  3 * st_polygon(list(
    -.5 + cbind(c(0, 1, 1, 0, 0), c(0, 0, 1, 1, 0)),
    -.25 + .5 * cbind(c(0, 1, 1, 0, 0), c(0, 0, 1, 1, 0))
  )
  )



the_clipped_voronoi <- the_voronoi |> 
  st_intersection(the_clip_with_hole)

the_voronoi |> plot()
the_points |> plot(add = TRUE)
the_clipped_voronoi |> plot(col = 'red', lwd = 3, add = TRUE)

Converting the result of st_voronoi to a clippable multipolygon turned out some hazzle.

clipping with polygon with hole

edit Alternative with {deldir}:

library(deldir)

the_points <- list(x = rnorm(10), y = rnorm(10))

## return Voronoi tesselation object (of class "deldir")
voronoi_object <- deldir(the_points)

corners <-  c(-1, 1, 1, -1, -1)

clip_with_hole <- 
  list(
    poly = list(x = .5 * corners,  y = .5 * rev(corners)),
    hole = list(x = .25 * corners, y = .25 * rev(corners))
  )

## return Voronoi polygons ("tiles") and plot
## original:
tile.list(voronoi_object) |> plot()
## clipped:
tile.list(voronoi_object, clipp = clip_with_hole) |>
  plot(lwd = 3, showpoints = FALSE, fillcol = rainbow(4), add = TRUE)

enter image description here

I_O
  • 4,983
  • 2
  • 2
  • 15
  • 1
    Thanks. I don't think **sf** handles constrained Delaunay/Voronoi tessellation and clipping to a polygon with a hole. Does it? For such a clipping, I've just thought I could use my non-CRAN package **cgalPolygons**. It handles intersections of polygons with holes. – Stéphane Laurent May 22 '23 at 20:13
  • Looks like intersections with polygons (with holes) are possible, too. I edited the answer accordingly. – I_O May 22 '23 at 20:47
  • Yeah, but this is not a constrained VoronoÏ diagram. I'l send you the link to a paper, whenever I'll retrieve it. Even the way I'm trying to use is not the right one. – Stéphane Laurent May 23 '23 at 07:50
  • I found an alternative way with {deldir}, see edited answer, please. (The Voronoi shards go as "tiles", somewhat confusingly). One has to set the constraints' coordinates separately though. – I_O May 23 '23 at 09:04