mapdeck icon indicating copy to clipboard operation
mapdeck copied to clipboard

Facility for initializing a map from (e.g.) an SP object

Open MichaelChirico opened this issue 5 years ago • 10 comments

I've got a SpatialPolygons object and I'd like to initialize my mapdeck() call with the right location and zoom to match this.

It's a bit tedious at the moment, along the lines of:

# p4s is WGS84
mySP = SpatialPolygons(...) # or readOGR(...)

get_zoom = function(b) {
  WIDTH = c(x = 360, y = 180)
  MAX_ZOOM = 18L
  zooms = c(x = NA_integer_, y = NA_integer_)
  for (dir in c('x', 'y')) {
    zooms[dir] = MAX_ZOOM + findInterval(diff(b[dir, ]), WIDTH[dir]/2^(MAX_ZOOM:0))
  }
  return(min(zooms))
}

mapdeck(
  token = my_token,
  location = rowMeans(bbox(mySP)),
  zoom = get_zoom(bbox(mySP))
)

Not sure what exactly to export/surface here, but something to facilitate here would be very helpful/convenient

MichaelChirico avatar Mar 20 '19 04:03 MichaelChirico

Are you talking about initialising the location before you call any add_scatterplot/add_polygon etc layers?

SymbolixAU avatar Mar 20 '19 04:03 SymbolixAU

Yes exactly

MichaelChirico avatar Mar 20 '19 06:03 MichaelChirico

Ok. And do you envisage this being one/two functions which will find the correct locations for different types of objects, like

get_zoom.sf <- function() { }

get_zoom.sp <- function() { }

get_zoom.data.frame <- function(lon, lat) { }

## and similar for get_location()

dcooley avatar Mar 20 '19 06:03 dcooley

The API I'm more open-ended on. But yes that looks good. Can probably limit to sp/sf classes for now...

I guess the alternative is something like a center_on argument to mapdeck itself (which would dispatch to get_zoom/get_location internally?

MichaelChirico avatar Mar 20 '19 11:03 MichaelChirico

I just did this in ceramic, using reproj and spex to abstract over format details. I could try to pull it out, keep it all in spex, or similar?

mdsumner avatar Mar 25 '19 05:03 mdsumner

I think this is easy enough to add as a small utility function in mapdeck.

For what it's worth, these are the zoom levels I found somewhere on Mapbox's site (but can't remember/find where)

var lonZoomLevel = [
    360, 180, 90, 45, 22.5, 11.25, 5.65,2.813, 1.406,
    0.703, 0.352, 0.176, 0.088, 0.044, 0.022, 0.011, 0.005
  ];

var latZoomLevel = [
    90, 45, 22.5, 11.25, 5.65,2.813, 1.406,
    0.703, 0.352, 0.176, 0.088, 0.044, 0.022, 0.011, 0.005, 0.0025, 0.000175
  ];

So just need to get the difference in lon & lat values of the bbox and index against these arrays.

SymbolixAU avatar Mar 25 '19 22:03 SymbolixAU

I'm thinking of when the spatial object is in a map projection, or would you restrict to only longlat data (and Mercator with a little more effort)?

mdsumner avatar Mar 25 '19 22:03 mdsumner

For what it's worth, these are the zoom levels I found somewhere on Mapbox's site (but can't remember/find where)

They're correct, see here and details from MapBox ref

(I'm not sure why the lat widths are sub-2^n, does mapbox truncate the poles by 5 degrees?)

MichaelChirico avatar Mar 26 '19 06:03 MichaelChirico

I'm thinking of when the spatial object is in a map projection, or would you restrict to only longlat data (and Mercator with a little more effort)?

All mapdeck functions assume data is in Web Mercator, so I'm not thinking about handling any other types. I'm expecting the user to have already set this correctly before entering mapdeck.

How does one know (from an sf / sp object), and how should it be handled if the data spans the international date line?

SymbolixAU avatar Mar 28 '19 21:03 SymbolixAU

Ugh, that's extremely problematic actually, because projecting forward or reverse will usually re-wrap longitudes into -180, 180. I'm more interested in general cases for local data, I'll just explore.

All mapdeck functions assume data is in Web Mercator

I don't understand that, it seems you assume data is longitude/latitude, I guess we have a terminology issue?

mdsumner avatar Mar 28 '19 22:03 mdsumner