Search code examples
rrandomsimulationspatial

create random points inside a shape in r


I'm trying to simulate some data for a project, and basically I need to draw an irregular oval-ish shape, then make a bunch of random points inside that shape, and I'm at a total loss for how to do this.

For now, I've made a spline shape, then plotted a bunch of points over it. Is there a way I can find the overlap? Or better, just generate random points in bounds of a pre-made shape?

(feel free to ditch my code if there is a better way to start - maybe it needs to be some kind of spatial object?)

set.seed(2)
shape <- data.frame(
  x     = c(2, 3, 2, 3, 2, 1, 0, 1),
  y     = c(1, 3, 5, 7, 9, 7, 5, 3 )
)

scatter = data.frame(
  x = rnorm(100, mean = 1.5, sd = .6),
  y = rnorm(100, mean = 5, sd = 2)
)


ggplot(data = shape, 
       aes(x=x,y=y)) +
  ggforce::geom_bspline_closed(fill = "transparent", color = "black") +
  geom_point(color = "blue") +
  coord_equal() +  
  geom_point(data = scatter, shape = "*", size=3)

enter image description here


Solution

  • I would recommend the sf package because it is made for spatial data and performing spatial operation. Here is a small example of generating random points within a polygon:

    library(ggplot2)
    
    polygon =
      # The syntax for creating a polygon with sf is a little strange.
      # It has to be a list of matrices and the first point has to be 
      # repeated as the last point (2, 1).
      list(
        matrix(
          c(2, 1, 3, 3, 2, 5, 3, 7, 2, 9, 1, 7, 0, 5, 1, 3, 2, 1),
          ncol=2, byrow=T
        )
      ) 
    
    # Create an sf polygon
    polygon = sf::st_polygon(polygon)
    # Sample 50 random points within the polygon
    points = sf::st_sample(polygon, size=50)
    
    # Plot using the ggplot geom_sf function.
    ggplot() + 
      geom_sf(aes(), data=polygon) + 
      geom_sf(aes(), data=points)
    

    enter image description here

    If you need the coordinates of the points, you can simply convert the sf point object to a data.frame with points %>% sf::st_coordinates() %>% as.data.frame().