jmlondon / pathroutr

R package for routing tracks around barrier polygons
https://jmlondon.github.io/pathroutr/
16 stars 2 forks source link

Problem with prt_visgraph() returning an empty network #12

Closed dcmo closed 1 year ago

dcmo commented 3 years ago

Hello - {pathroutr} is exactly what I've been looking for, thank you! I'm hoping to use {pathroutr] for plotting potential paths around the coast for seabirds, given a start and end point. To date, I have been using Matlab and A* pathways (very slow computation times!) but have recently switched to R and have been looking for a better way to define the paths.

To understand how the package works, I have been working though the "Re-routing Straight Line Paths Around Barriers - A Visibility Graph Demo" example, modifying the code for my own data. Everything is looking great up until I try to make the visibility graph using prt_visgraph().

In my case I have paths around the UK coast so I am using

land_barrier <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf")  %>%
    dplyr::filter(admin == "United Kingdom")  %>% dplyr::select(admin)

But prt_visgraph(land_barrier, buffer = 150) (for any value of buffer) returns

# A sfnetwork with 1 nodes and 0 edges
#
# CRS:  +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0 
#
# An unrooted tree with spatially explicit edges
#
# Node Data:     1 x 1 (active)
# Geometry type: POINT
# Dimension:     XY
# Bounding box:  xmin: NA ymin: NA xmax: NA ymax: NA
     geometry
  <POINT [°]>
1       EMPTY
#
# Edge Data: 0 x 4
# ... with 4 variables: from <int>, to <int>, geometry <GEOMETRY [°]>, weight [m]
Warning messages:
1: In st_cast.sf(barrier, "POLYGON") :
  repeating attributes for all sub-geometries for which they may not be constant
2: In st_triangulate.sfc(., bOnlyEdges = TRUE) :
  st_triangulate does not correctly triangulate longitude/latitude data

Based on the discussion in #7 I also tried changing the crs

land_barrier <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf")  %>%
    dplyr::filter(admin == "United Kingdom")  %>% dplyr::select(admin) %>% 
    st_transform(., crs = 4326) %>%
    sf::st_make_valid()

but the result is the same. This is my first attempt at understanding/using sfnetworks so I'm at a loss what to try next. The 'edges' look like this, but I don't yet understand if thats right or not. Has anyone else tried the UK polygon? (I know I need to add Ireland but this is just a test for now)

Rplot02

Originally posted by @dcmo in https://github.com/jmlondon/pathroutr/discussions/6#discussioncomment-1389375

jmlondon commented 3 years ago

[note: Deena and I originally covered this in a Discussion but I moved it here for better discoverability and tracking]

Deena (@dcmo)

I'm glad to hear {pathroutr} has potential use for your analysis. And, thank you for the reproducible example.

I took a quick look and it seems the issue is that prt_visgraph() doesn't support geographic (lat/long) POLYGON/MULTIPOLYGON data. That said, I don't have any checks or documentation that specifies this. So, there's no way you would have known. I'll add in some checks so geographic data throws a meaningful error.

Could I ask a favor and have you copy your post/example over to an 'issue' (https://github.com/jmlondon/pathroutr/issues)? I can then follow up once I've made improvements related to this.

In your example, we just need to transform the land barrier from natural earth into a UK projection (below, I chose the OSGB 1936 / British National Grid -- United Kingdom Ordnance Survey; EPSG:277000). And, note, you'll also need to transform your track points to the same projection.

library(rnaturalearth)
library(tidyverse)
library(sf)
library(pathroutr)

land_barrier <- rnaturalearth::ne_countries(scale = "medium", returnclass = "sf")  %>%
  dplyr::filter(admin == "United Kingdom")  %>% dplyr::select(admin)

land_barrier <- land_barrier %>% 
  st_set_crs('EPSG:4326') %>% 
  st_transform('EPSG:27700')

vg <- prt_visgraph(land_barrier)
# A sfnetwork with 963 nodes and 1958 edges
#
# CRS:  EPSG:27700 
#
# An undirected simple graph with 1 component with spatially explicit edges
#
# Node Data:     963 × 1 (active)
# Geometry type: POINT
# Dimension:     XY
# Bounding box:  xmin: 1934.552 ymin: 18456.26 xmax: 654566.2 ymax: 1217133
             geometry
          <POINT [m]>
1  (465248.8 1217083)
2  (466786.1 1214963)
3  (464071.5 1217133)
4  (459088.3 1214659)
5 (104878.3 936975.3)
6   (101207.9 932765)
# … with 957 more rows
#
# Edge Data:     1,958 × 4
# Geometry type: LINESTRING
# Dimension:     XY
# Bounding box:  xmin: 1934.552 ymin: 18456.26 xmax: 654566.2 ymax: 1217133
   from    to                             geometry weight
  <int> <int>                     <LINESTRING [m]>    [m]
1     1     2 (465248.8 1217083, 466786.1 1214963)  2619.
2     1     3 (464071.5 1217133, 465248.8 1217083)  1178.
3     3     4 (459088.3 1214659, 464071.5 1217133)  5563.
# … with 1,955 more rows
plot(vg)

image