How to clip some polygons to the boundary of another polygon?

122 Views Asked by At

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).

1

There are 1 best solutions below

4
I_O On

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