Skip to content

Commit

Permalink
add possibility to automatically mapview some environment
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-salabim committed Mar 15, 2020
1 parent d6b490e commit 7abf070
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 112 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Suggests:
covr,
dplyr,
knitr,
later,
lwgeom,
mapdeck,
plainview,
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export(mapviewGetOption)
export(mapviewOptions)
export(mapviewOutput)
export(mapviewPalette)
export(mapviewWatcher)
export(npts)
export(plainView)
export(plainview)
Expand All @@ -42,6 +43,8 @@ export(renderMapview)
export(renderslideView)
export(slideViewOutput)
export(slideview)
export(startWatching)
export(stopWatching)
export(sync)
export(viewExtent)
export(viewRGB)
Expand Down
95 changes: 7 additions & 88 deletions R/mapView.R
Original file line number Diff line number Diff line change
Expand Up @@ -1083,101 +1083,20 @@ setMethod('mapView', signature(x = 'NULL'),
setMethod('mapView', signature(x = 'list'),
function(x,
map = NULL,
zcol = NULL,
burst = FALSE,
color = mapviewGetOption("vector.palette"),
col.regions = mapviewGetOption("vector.palette"),
at = NULL,
na.color = mapviewGetOption("na.color"),
cex = 6,
lwd = lapply(x, lineWidth),
alpha = lapply(seq(x), function(i) 0.9),
alpha.regions = lapply(seq(x), function(i) 0.6),
map.types = mapviewGetOption("basemaps"),
verbose = mapviewGetOption("verbose"),
popup = lapply(seq(x), function(i) {
leafpop::popupTable(x[[i]])
}),
layer.name = deparse(substitute(x,
env = parent.frame())),
label = lapply(seq(x), function(i) {
makeLabels(x[[i]], zcol = zcol[[i]])
}),
legend = mapviewGetOption("legend"),
legend.opacity = 1,
homebutton = TRUE,
native.crs = FALSE,
maxpoints = NULL, #lapply(x, getMaxFeatures),
...) {

lyrnms = makeListLayerNames(x, layer.name)

if (!is.list(color))
color <- rep(list(color), length(x))
if (!is.list(col.regions))
col.regions <- rep(list(col.regions), length(x))
if (!is.list(legend))
legend <- rep(list(legend), length(x))
if (!is.list(homebutton))
homebutton <- rep(list(homebutton), length(x))
if (!is.list(cex))
cex <- rep(list(cex), length(x))
if (!is.list(lwd))
lwd <- rep(list(lwd), length(x))
# if (!is.list(highlight))
# highlight <- rep(list(highlight), length(x))
# if (!is.list(label))
# label <- rep(list(label), length(x))
if (length(popup) != length(x))
popup <- rep(list(popup), length(x))
if (length(alpha) != length(x))
alpha <- rep(list(alpha), length(x))
if (length(alpha.regions) != length(x))
alpha.regions <- rep(list(alpha.regions), length(x))

m <- Reduce("+", lapply(seq(x), function(i) {
mapView(x = x[[i]],
layer.name = lyrnms[[i]],
...)
}))@map

if (mapviewGetOption("platform") == "leaflet") {
m <- Reduce("+", lapply(seq(x), function(i) {
if (is.null(popup)) popup <- leafpop::popupTable(x[[i]])
if (inherits(x[[i]], "sf")) {
mapView(x = sf::st_cast(x[[i]]),
layer.name = lyrnms[[i]],
zcol = zcol[[i]],
color = color[[i]],
col.regions = col.regions[[i]],
legend = legend[[i]],
label = label[[i]],
popup = popup[[i]],
homebutton = homebutton[[i]],
native.crs = native.crs,
cex = cex[[i]],
lwd = lwd[[i]],
map.types = map.types,
alpha = alpha[[i]],
alpha.regions = alpha.regions[[i]],
burst = FALSE,
...)
} else {
mapView(x = sf::st_cast(x[[i]]),
layer.name = lyrnms[[i]],
homebutton = homebutton[[i]],
native.crs = native.crs,
cex = cex[[i]],
lwd = lwd[[i]],
map.types = map.types,
burst = FALSE,
...)
}
}))@map
m <- leaflet::hideGroup(map = m,
group = layers2bHidden(m, ...))
out <- new("mapview", object = x, map = m)
# print(str(out@map), 4)
# stop("hallo")
return(out)
} else {
NULL
}
out <- new("mapview", object = x, map = m)
return(out)
}
)

Expand Down
4 changes: 2 additions & 2 deletions R/mapviewControls.R
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,9 @@ makeLayerName = function(x, zcol = NULL, up = 3) {


makeListLayerNames = function(x, layer.name) {
if (length(layer.name) == length(x)) {
if (length(layer.name) == length(x) & !(is.list(x))) {
lnms = layer.name
} else if (!is.null(names(x))) {
} else if (is.list(x) & !(is.null(names(x)))) {
lnms = names(x)
} else {
chr = gsub(utils::glob2rx("*list(*"), "", layer.name)
Expand Down
25 changes: 24 additions & 1 deletion R/mapviewOptions.R → R/options.R
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
#' @param cex numeric or attribute name(s) or column number(s) in attribute table
#' of the column(s) to be used for defining the size of circles.
#' @param alpha opacity of lines.
#' @param watch whether to watch a certain environment and automatically
#' render cahnges to the list of spatial data in that environment. See
#' \link{mapviewWatcher} for details.
#'
#' @author
#' Tim Appelhans
Expand Down Expand Up @@ -147,7 +150,8 @@ mapviewOptions <- function(platform,
cex,
alpha,
default = FALSE,
console = TRUE) {
console = TRUE,
watch = FALSE) {

### 1. global options -----

Expand Down Expand Up @@ -367,6 +371,21 @@ mapviewOptions <- function(platform,
}
}

## watch
setWatcher = function(watch) {
options(mapviewWatcher = watch)
}

.watch = function() {
default = FALSE
wtch = getOption("mapviewWatcher")
if (is.null(wtch)) {
return(default)
} else {
return(wtch)
}
}

### 2. raster relevant options -----


Expand Down Expand Up @@ -706,6 +725,7 @@ mapviewOptions <- function(platform,
options(mapviewViewerSuppress = FALSE)
options(mapviewHomebutton = TRUE)
options(mapviewNativeCRS = FALSE)
options(mapviewWatcher = FALSE)

## raster
options(mapviewraster.size = 8 * 1024 * 1024)
Expand Down Expand Up @@ -754,6 +774,7 @@ mapviewOptions <- function(platform,
}
if (!missing(homebutton)) { setHomebutton(homebutton); cnt <- cnt + 1 }
if (!missing(native.crs)) { setNativeCRS(native.crs); cnt <- cnt + 1 }
if (!missing(watch)) { setWatcher(watch); cnt <- cnt + 1 }


## raster
Expand Down Expand Up @@ -800,6 +821,7 @@ mapviewOptions <- function(platform,
, viewer.suppress = .viewerSuppress()
, homebutton = .homebutton()
, native.crs = .nativeCRS()
, watch = .watch()

## raster
, raster.size = .rasterSize()
Expand Down Expand Up @@ -845,6 +867,7 @@ mapviewOptions <- function(platform,
cat('viewer.suppress :', lst$viewer.suppress, '\n')
cat('homebutton :', lst$homebutton, '\n')
cat('native.crs :', lst$native.crs, '\n')
cat('watch :', lst$watch, '\n')

## raster
cat("\n raster data related options: \n\n")
Expand Down
140 changes: 140 additions & 0 deletions R/watch.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#' Start and/or stop automagic mapviewing of spatial objects in your workspace.
#'
#' @description
#' Use these functions to enable automatic vieweing of all spatial objects
#' currently available in \code{env}. \code{mapviewWatcher} uses
#' \link[later]{later} to set up a watcher function that continuously monitors
#' \code{env} for spatial objects and refreshes the viewer/browser in case
#' the list of spatial objects changes.
#' \cr
#' \cr
#' \code{startWatching} and \code{stopWatching} are convenience functions to
#' start and stop watching, respectively.
#'
#' @details
#' \code{mapviewWatcher} uses \code{\link{identical}} and hence
#' will redraw even if e.g. the attributes of a spatial object are changed only
#' slightly. By default \code{mapviewWatcher} watches the \code{.GlobalEnv} but
#' this can be changed to another environment. Whether watching is turned on is
#' controlled by \code{mapviewGetOption("watch")}. In order to enable watching it
#' needs to be set to \code{mapviewOptions(watch = TRUE)}
#' (default is \code{FALSE}) and the watcher needs to be initiated by calling
#' \code{mapviewWatcher()} once. To switch watching off it is sufficient to set
#' \code{mapviewOptions(watch = FALSE)}.
#'
#' @param env the environemnt that is being watched (default is \code{.GlobalEnv}).
#' @param ... currently not used.
#'
#' @examples
#' if (interactive()) {
#' library(mapview)
#'
#' ## start the watcher
#' mapview::startWatching()
#'
#' ## load some data and watch the automatic visualisation
#' fran = mapview::franconia
#' brew = mapview::breweries
#'
#' ## stop the watcher
#' mapview::stopWatching()
#'
#' ## loading or removing things now will not trigger a view update
#' rm(brew)
#' trls = mapview::trails
#'
#' ## re-starting the viewer will re-draw whatever is currently available
#' mapview::startWatching()
#'
#' ## watcher can also be stopped via mapviewOptions
#' mapviewOptions(watch = FALSE)
#'
#' rm(trls)
#'
#' }
#'
#' @export
#' @rdname mapviewWatcher
mapviewWatcher = function(env = .GlobalEnv, ...) {

if (!requireNamespace("later", quietly = TRUE)) {
stop(
"Please install.packages('later') to allow mapview to watch your workspace"
, call. = FALSE
)
}

last_value = NULL

dir <- tempfile()
dir.create(dir)
htmlFile <- file.path(dir, "index.html")

mv_watch = function() {
if (!mapviewGetOption("watch")) return(invisible())
spatdat_lst = getSpatialData(env = env)
if (length(spatdat_lst) > 0 && !identical(spatdat_lst, last_value)) {
m = mapview::mapView(spatdat_lst)
mapview::mapshot(m, htmlFile)

viewer <- getOption("viewer")
if (!is.null(viewer)) {
viewer(htmlFile)
} else {
utils::browseURL(htmlFile)
}
last_value <<- spatdat_lst
}

later::later(mv_watch, 0.25)
}

## initiate the watcher
mv_watch()
}

#' @export
#' @describeIn mapviewWatcher start watching
startWatching = function(env = .GlobalEnv, ...) {
mapviewOptions(watch = TRUE)
mapviewWatcher(env = env)
}

#' @export
#' @describeIn mapviewWatcher stop watching
stopWatching = function(env = .GlobalEnv, ...) {
mapviewOptions(watch = FALSE)
}


## helper
getSpatialData = function(env = .GlobalEnv) {
dat = ls(envir = env, sorted = FALSE)
cls = lapply(lapply(dat, get), class)

## sf
sf_idx = grep("sf", cls)
sf_dat = as.list(dat[sf_idx])
names(sf_dat) = dat[sf_idx]

## sp
sp_idx = grep("Spatial", cls)
sp_dat = as.list(dat[sp_idx])
names(sp_dat) = dat[sp_idx]

# stars
st_idx = grep("stars", cls)
st_dat = as.list(dat[st_idx])
names(st_dat) = dat[st_idx]

## raster
rs_idx = grep("Raster", cls)
rs_dat = as.list(dat[rs_idx])
names(rs_dat) = dat[rs_idx]

## combine and get
spatdat = Filter(Negate(is.null), c(sf_dat, sp_dat, st_dat, rs_dat))

lapply(spatdat, get)
}

19 changes: 0 additions & 19 deletions man/mapView.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 7abf070

Please sign in to comment.