Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misalignment problem when curvilinear raster grid are ploted as regular ones #461

Open
GillesSanMartin opened this issue Oct 24, 2023 · 0 comments

Comments

@GillesSanMartin
Copy link

I came across an unexpected behavior of mapview (?) :
I create a vector grid with sf:st_make_grid then I transform it into a terra raster object. When I plot both with mapview they are misaligned.

After my question on stackoverflow, Robert Hijman suggested that it was a problem with the Mercator projection used in mapview that should produce a curvilinear grid but is represented with a regular grid (NB: I paraphrase with my own words and understanding)

Here is a reproducible example :

library(sf)
library(terra)
library(stars)
library(ggplot2)
library(mapview)

my_cellsize <- 50000

# Load the 'nc' shapefile from the sf package
nc <- st_read(system.file("shape/nc.shp", package = "sf")) |> 
    st_transform(crs = 32617) # projection in meters

# Create a grid within the extent of the 'nc' dataset
my_grid <-  st_make_grid(nc, cellsize = my_cellsize)
my_grid <- st_sf(GridID = 1:length(my_grid), my_grid)
my_grid <- my_grid[nc,]

# add some random values
my_grid$value1 <- rnorm(nrow(my_grid))

# convert the vector grid into a raster stack
template = rast(vect(my_grid), res = my_cellsize)
value1_raster <- rasterize(vect(my_grid), template, field = "value1")

Various calls to mapview showing the misalignment

# With a simple call to mapview the vector grid and the raster grid are not aligned
mapview(st_as_stars(value1_raster) ) + mapview(my_grid)

# Transforming to the Mercator projection used by mapview does not help
# But the misalignment is different
mapview(st_as_stars(value1_raster) |> st_transform(crs = "+proj=webmerc +datum=WGS84")) + 
    mapview(my_grid |> st_transform(crs = "+proj=webmerc +datum=WGS84"))

# using st_warp instead of st_transform seems to simply reproduce what is done by mapview in the backgroud
mapview(st_as_stars(value1_raster) |> st_warp(crs = "+proj=webmerc +datum=WGS84")) + 
    mapview(my_grid |> st_transform(crs = "+proj=webmerc +datum=WGS84"))

Various calls to other plotting approaches that seem to work fine :

# The raster and the vector grid are correctly 
# plotted with a simple call to plot on the terra objects : 

plot(value1_raster, reset = TRUE)
lines(my_grid, col = "red")

# Using stars, we can also have a correct alignment of a curvilinear raster grid with the vector
# This is what I would expect to see in mapview

stars::st_as_stars(value1_raster) |> 
    st_transform(crs = "+proj=webmerc +datum=WGS84") |> 
    plot(reset = FALSE)
my_grid |> st_transform(crs = "+proj=webmerc +datum=WGS84") |> st_geometry() |> 
    plot(add = TRUE, reset = FALSE, border = "red", lwd = 2, color = NA)

# Same with ggplot : 
ggplot() +
    geom_stars(data = st_transform(st_as_stars(value1_raster), 
                                   crs = "+proj=webmerc +datum=WGS84"), 
               alpha = 0.8, downsample = c(0, 0, 0)) +
    geom_sf(data = st_transform(my_grid, crs = "+proj=webmerc +datum=WGS84"), 
            color = "red", fill = NA) +
    theme_void()

Again, as pointed out by Robert Hijmans, one way to get a correct plot in mapview would be to use the Mercator projection from the beginning. But that does not seem to be a usable solution in real life where you might need other projections adapted to your local conditions to compute areas, distances, etc.

my_cellsize <- 50000
nc <- st_read(system.file("shape/nc.shp", package = "sf")) |> 
    st_transform(crs = "+proj=webmerc +datum=WGS84") 
my_grid <-  st_make_grid(nc, cellsize = my_cellsize)
my_grid <- st_sf(GridID = 1:length(my_grid), my_grid)
my_grid <- my_grid[nc,]
my_grid$value1 <- rnorm(nrow(my_grid))
template = rast(vect(my_grid), res = my_cellsize)
value1_raster <- rasterize(vect(my_grid), template, field = "value1")

mapview(st_as_stars(value1_raster)) + mapview(st_as_sf(as.lines(vect(my_grid))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant