6

I would like to create evenly spaced polylines going North to South with 50 mile spacing between each line and 10 miles long. Not sure if this is possible using sf package. In the example below, I would like to have the lines filling the counties across the state of Washington.


library(tigris)
library(leaflet)

states <- states(cb = TRUE)

counties<-counties(cb=TRUE)

counties<- counties%>%filter(STATEFP==53)

states<- states%>%filter(NAME=="Washington")

leaflet(states) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addPolygons(fillColor = "white",
              color = "black",
              weight = 0.5) %>%
  addPolygons(data=counties,color='red',fillColor = 'white')%>%
  setView(-120.5, 47.3, zoom=8)

I've updated to include an image of what I'd like to do below.enter image description here

jsimpsno
  • 448
  • 4
  • 19

1 Answers1

3

You can create a multilinestring sf object from scratch by specifying coordinates.

You can get these coordinates from the extent (bounding box) of Washington, but you may also be interested in knowing how to create a grid, which I will demonstrate below because it may be helpful.

Copy and paste this reproducible example:

library(tidyverse)
library(tigris)
library(leaflet)
library(sf)
library(raster)

states <- states(cb = TRUE)

# subset for WA and transform to a meter-based CRS 
states <- states %>% 
  filter(NAME == "Washington") %>% 
  st_transform(crs = 3857) # Mercator

# fifty miles in meters
fm <- 80467.2

# subset for Washington
states_sp <- as(states, "Spatial")

# create a grid, convert it to polygons to plot
grid <- raster(extent(states_sp), 
               resolution = c(fm, fm), 
               crs = proj4string(states_sp))
grid <- rasterToPolygons(grid)
plot(states_sp)
plot(grid, add = TRUE)

# find the top y coordinate and calculate 50 mile intervals moving south
ty <- extent(grid)[4]  # y coordinate along northern WA edge
ty <- ty - (fm * 0:7)  # y coordinates moving south at 10 mile intervals

# create a list of sf linestring objects
l <- vector("list", length(ty))
for(i in seq_along(l)){
  l[[i]]  <- 
    st_linestring(
      rbind(
        c(extent(grid)[1], ty[i]),
        c(extent(grid)[2], ty[i])
      )
    )
}

# create the multilinestring, which expects a list of linestrings
ml <- st_multilinestring(l) 

plot(states_sp)
plot(as(ml, "Spatial"), add = TRUE, col = "red")

As you can see, I switch back and forth between sf and sp objects using the functions as(sf_object, "Spatial") and st_as_sf(sp_object). Use these to transform the data to your needs.

enter image description here

Rich Pauloo
  • 7,734
  • 4
  • 37
  • 69
  • This is fairly close to what I'm after. I've updated the question with an image of what I am trying to achieve. Is this possible with your code? Also, if no other answers I'll reward you the check if I can't get exactly what I'm after. Appreciate your help! – jsimpsno Oct 28 '20 at 03:01
  • To the best of my knowledge, there's no out of the box function to create exactly what you're looking for, so you'll need to create a multilinestring object from scratch by measuring distances in a meter-based CRS, iterating over a list to define lines `st_linestring(rbind(c(x1, y1), c(x2,y1)))`, and then binding these list elements into a single multilinestring object with `st_multilinestring(my_list_of_lines)`. What I provided should get you most of the way there, you just need to change the coordinates. – Rich Pauloo Oct 28 '20 at 17:53
  • 1
    Sounds good. I just realized i could also split the lines every X miles as well so this will work. Thanks again! – jsimpsno Oct 28 '20 at 18:01