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

Add coord_bc() function to specify ggplot2 bounding box in lat/long #65

Open
schckngs opened this issue Jul 14, 2020 · 12 comments
Open

Comments

@schckngs
Copy link

Hi,
This is a great package and I'm starting to use it more often.
I'm posting here to get input on mapping sub-regions of BC using ggplot with the bc_bound_hres().
Currently for quickly mapping I convert the lat/lon of my study area to UTM and enter in coord_sf(), e.g.:
ggplot() + geom_sf(bc_bound_hres(), fill = "grey", colour = "black") + coord_sf(xlim = c(600000, 800000), ylim = c(745000, 1000000))
If it is possible to set limits in lat/lon it would be faster and more intuitive, but I haven't figured out how best to do that yet. Pardon if there is an obvious way of doing this.
Cheers!

@ateucher
Copy link
Collaborator

Hi @schckngs, this is a good question!

You can set it using lat/long if you specify crs=st_crs(4326) in the coord_sf() call, but it then reprojects the whole map to lat/long WGS84, which doesn't give a faithful representation of BC (think of how it looks in Google Maps):

library(sf)
#> Linking to GEOS 3.8.1, GDAL 3.1.1, PROJ 6.3.1
library(bcmaps)
library(ggplot2)
ggplot() + 
  geom_sf(data = bc_bound(), fill = "grey", colour = "black") + 
  coord_sf(xlim = c(-132, -129), ylim = c(51.5, 54), crs = st_crs(4326))

Created on 2020-07-16 by the reprex package (v0.3.0)

I think there may be space in bcmaps for a small function (coord_bc()?) that converts it on the fly for you, it could be pretty handy! Here is a prototype. It requires a bit more testing, but let me know if this is what you are thinking of:

library(sf)
library(bcmaps)
library(ggplot2)

coord_bc <- function(xlim, ylim, crs = sf::st_crs(4326), ...) {
  box <- sf::st_bbox(c(xmin = min(xlim), xmax = max(xlim), 
                       ymin = min(ylim), ymax = max(ylim)), 
                     crs = crs)
  box <- sf::st_bbox(
    sf::st_transform(sf::st_as_sfc(box), sf::st_crs(3005))
  )
  
  ggplot2::coord_sf(xlim = box[c("xmin", "xmax")], 
                    ylim = box[c("ymin", "ymax")], 
                    ...)
}

ggplot() + 
  geom_sf(data = bc_bound(), fill = "grey", colour = "black") + 
  coord_bc(xlim = c(-132, -129), ylim = c(51.5, 54))

Created on 2020-07-16 by the reprex package (v0.3.0)

Thoughts @stephhazlitt @boshek @gcperk?

@schckngs
Copy link
Author

Thank you! This is great.

@stephhazlitt
Copy link
Member

stephhazlitt commented Jul 21, 2020

I think this would be a great additional helper function in the bcmaps 📦 @ateucher. I added this enhancement issue to the v0.2.0 project board. Great idea, thanks @schckngs.

@stephhazlitt stephhazlitt added this to the v0.2 milestone Jul 21, 2020
@ateucher ateucher changed the title Drawing sub-regions Add coord_bc() function to specify ggplot2 bounding box in lat/long Jul 21, 2020
@boshek
Copy link
Collaborator

boshek commented Aug 6, 2020

Using this a little I am seeing that I am really choosing one of the features (or collection of features) to defining this window. Having to find the bounding box of that feature and then manually extract the limits is a little clunky. What if coord_bc directly accepted a bounding features then transformed that:

coord_bc <- function(bounding_feature = NULL, ...) {
  
  if (!inherits(bounding_feature, "sf")) {
    stop("bounding_feature is not an sf object")
  }

  box <- sf::st_bbox(
    sf::st_transform(bounding_feature, sf::st_crs(3005))
  )

  ggplot2::coord_sf(xlim = box[c("xmin", "xmax")],
                    ylim = box[c("ymin", "ymax")],
                    ...)
}

@ateucher
Copy link
Collaborator

I think that would be a different (but welcome) function @boshek - I think it's quite common to just want your plot zoomed in on a particular area by specifying lat/long

@boshek
Copy link
Collaborator

boshek commented Aug 12, 2020

Would it make sense to have coord_bc accept both lat/long or a bbox?

@ateucher
Copy link
Collaborator

Possibly, though a couple of things:

  1. I sort of feel that coord_bc should mimic as much as possible coord_sf, i.e., have xlim and ylim args. We could dispatch on xlim (it could be a two element numeric vector or a bbox object), but that feels clunky.

  2. If you're clipping based on a specific bbox or another feature, why not do that before plotting with st_intersection? I see using coord_sf/bc as more iterative when you're plotting, which is why I like the easy flexibility of xlim and ylim (I.e., zooming in vs a-priori selecting a specific area to show).

@boshek
Copy link
Collaborator

boshek commented Aug 13, 2020

I think you are definitely right that we don't want to change the syntax or behaviour of coord_sf. The attractive thing for me was that the coord_bc performed that intersection on all the layers on the fly.

@stephhazlitt
Copy link
Member

Bumping this issue, as I came across another user looking for the feature.

@stephhazlitt stephhazlitt removed this from the v0.2 milestone Jun 4, 2023
@ateucher
Copy link
Collaborator

Just coming back to this - I realized that the original use case defined by @schckngs can be achieved by specifying xlim and ylim in lat/long, and setting the default_crs argument to 4326 (WGS84). As you can see this keeps the map in the CRS of the original data:

library(sf)
library(bcmaps)
library(ggplot2)
ggplot() + 
  geom_sf(data = bc_bound(), fill = "grey", colour = "black") + 
  coord_sf(xlim = c(-132, -129), ylim = c(51.5, 54), default_crs = 4326)

Created on 2023-11-20 with reprex v2.0.2

@ateucher
Copy link
Collaborator

ateucher commented Nov 21, 2023

So is it worth implementing @boshek's suggestion to specify an sf[c] object or bbox? It's a more general problem than just B.C. though

@schckngs
Copy link
Author

Hey @ateucher and all - it has been a while since I looked at this page. Thanks for keeping the conversation going!
Reflecting on this - personally, being more familiar now with the sf package and coord_sf(), having a function like this is not as useful. But it sounds like it could be helpful for users new to R or sf/bcmaps (I recall getting going with sf being quite a struggle).
Perhaps it's worth adding some of the code above to the documentation instead of making a new function?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants