Search code examples
rsimulationpoint

R simulate spatial point data with points a maximum distance from previous point


I want to generate point data within a polygon where I provide a starting point and generate n points, where each point is generated within a maximum radius of the previous point. This is based on the assumption that an object that I'm tracking can only travel a maximum distance between two ping intervals.

The spatstat::rSSI function does something similar but it specifies a minimum distance between points whereas I want a maximum distance and for it to be from the previous point not all points. https://gis.stackexchange.com/questions/163287/randomly-sampling-points-in-r-with-minimum-distance-constraint


Solution

  • here is a first approach

    #set start point
    start <- matrix( data = c( 5, 52), ncol = 2, dimnames = list( "", c("lon", "lat")  ) )
    # lon lat
    #   5  52
    n = 10 #how many points from startpoint?
    max_dist = 100 #maximum distance to previous point in metres
    
    #pre-allocate
    L <- vector( mode = "list", length = 1+n )
    #and initialise startpoint
    L[[1]] <- start
    
    library( geosphere )
    set.seed(123) #for reproduction only, remove in production!
    for ( i in 2:(n+1) ) {
      L[[i]] <- geosphere::destPoint( p = L[[i-1]], #start = previous point
                                      b = runif(1, 0, 360), #random bearing bewteen 0 and 360 degrees
                                      d = runif(1, 0, max_dist ) #random distanxe between 0 and max_dist
                                    )
    }
    #transform to a data.table
    library( data.table )
    ans <- data.table::rbindlist( lapply( L, as.data.table ), use.names = TRUE, fill = TRUE)
    #         lon      lat
    # 1: 5.000000 52.00000
    # 2: 5.000336 51.99966
    # 3: 5.000835 51.99979
    # 4: 5.000546 52.00016
    # 5: 5.000907 51.99989
    # 6: 5.001065 51.99983
    # 7: 5.000414 52.00002
    # 8: 5.001240 52.00046
    # 9: 5.001055 52.00062
    #10: 5.000992 52.00113
    #11: 5.000553 52.00109
    
    #visual confirmation
    library(sf)
    library(leaflet)
    leaflet( data = ans) %>% addTiles() %>%
      addCircleMarkers( lng = ~lon, lat = ~lat ) %>%
      addPolylines( lng = ~lon, lat = ~lat )
    

    enter image description here

    not implemented: polygon boundaries, since no sample data is provided and I'm a lazy boy ;-) You could include a test inside the for loop to see if the new coordinates are within boundaries of the polygon, and if not; recalculate.