From 275c9dd8053459297a7baf8e08c9b0590411227d Mon Sep 17 00:00:00 2001 From: mtennekes Date: Fri, 22 Mar 2024 00:14:06 +0100 Subject: [PATCH] updated tm_labels, added Africa example --- NAMESPACE | 2 + R/misc_other.R | 88 +++++++++++++++---- R/tm_layers_text.R | 76 +++++++++++----- R/tm_scale_.R | 15 +++- R/tmapGrid_layers.R | 21 ++++- R/tmapScaleRGB.R | 33 ------- R/tmapScale_defaults.R | 2 +- examples/tm_symbols.R | 26 +++--- examples/tm_text.R | 112 ++++++------------------ man/tm_scale.Rd | 3 - man/tm_symbols.Rd | 26 +++--- man/tm_text.Rd | 193 ++++++++++++++++------------------------- 12 files changed, 290 insertions(+), 307 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 39673eb4..5ec0cd94 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -120,6 +120,8 @@ S3method(tmapSubsetShp,stars) export(get_fact_levels_na) export(make_by_vars) export(marker_icon) +export(opt_tm_labels) +export(opt_tm_text) export(providers) export(qtm) export(renderTmap) diff --git a/R/misc_other.R b/R/misc_other.R index 04848f3f..d543cc82 100644 --- a/R/misc_other.R +++ b/R/misc_other.R @@ -358,35 +358,87 @@ native_to_npc_to_native <- function(x, scale) { (x) / (scale[2] - scale[1]) } -.rectGrob2pathGrob <- function(rg, angles) { - x <- convertX(rg$x, "inch", valueOnly=TRUE) - y <- convertY(rg$y, "inch", valueOnly=TRUE) - w <- convertWidth(rg$width, "inch", valueOnly=TRUE) - h <- convertHeight(rg$height, "inch", valueOnly=TRUE) +.rectGrob2pathGrob <- function(rg, angles, bbx) { + x = as.numeric(rg$x) + y = as.numeric(rg$y) + w = as.numeric(rg$width) + h = as.numeric(rg$height) + + + #################################### + ### borrowed from pointLabel2 + #################################### + + + asp = tmaptools::get_asp_ratio(bbx)# * 1.25 + + #xyAspect <- diff(boundary[c(1,2)]) / diff(boundary[c(3,4)]) + + toUnityCoords <- function(xy) { + if (asp > 1) { + list(x = (xy$x - bbx[1])/(bbx[3] - bbx[1]) * asp, + y = (xy$y - bbx[2])/(bbx[4] - bbx[2])) + } else { + list(x = (xy$x - bbx[1])/(bbx[3] - bbx[1]), + y = (xy$y - bbx[2])/(bbx[4] - bbx[2])/asp) + } + + + } + toUserCoords <- function(xy) { + if (asp > 1) { + list(x = bbx[1] + xy$x/asp * (bbx[3] - bbx[1]), + y = bbx[2] + xy$y * (bbx[4] - bbx[2])) + } else { + list(x = bbx[1] + xy$x * (bbx[3] - bbx[1]), + y = bbx[2] + xy$y * asp * (bbx[4] - bbx[2])) + } + + } + xy <- xy.coords(x, y, recycle = TRUE) + z <- toUnityCoords(xy) + x2 <- z$x + y2 <- z$y + + # CHANGED: width and height are specified by user + if (asp > 1) { + w2 <- ((w) / (bbx[3] - bbx[1])) * asp + h2 <- ((h) / (bbx[4] - bbx[2])) + } else { + w2 <- ((w) / (bbx[3] - bbx[1])) + h2 <- ((h) / (bbx[4] - bbx[2])) / asp + } - a <- atan2(h, w) + + #################################### + #################################### + #################################### + + + xs = c(x2 - w2/2, x2 + w2 / 2, x2 + w2 / 2, x2 - w2 / 2, x2 - w2/2) + ys = c(y2 - h2/2, y2 - h2 / 2, y2 + h2 / 2, y2 + h2 / 2, y2 - h2/2) + + a <- atan2(h2, w2) + #as <- as.vector(vapply(a, function(a)c(a,pi-a, pi+a,-a), numeric(4))) as <- as.vector(vapply(a, function(a)c(a,pi-a, pi+a,-a), numeric(4))) as2 <- as + rep(angles * pi / 180, each=4) - dst <- rep(sqrt((w/2)^2+(h/2)^2), each=4) - - xs <- rep(x, each=4) + cos(as2) * dst - ys <- rep(y, each=4) + sin(as2) * dst + dst <- rep(sqrt((w2/2)^2+(h2/2)^2), each=4) - xs2 <- convertX(unit(xs, "inch"), "npc") - ys2 <- convertY(unit(ys, "inch"), "npc") + xs2 <- rep(x2, each=4) + cos(as2) * dst + ys2 <- rep(y2, each=4) + sin(as2) * dst id <- rep(1:length(x), each=4) - w2 <- w + (h-w) * abs(sin(angles*pi/180)) - h2 <- h + (w-h) * abs(sin(angles*pi/180)) + #w2 <- w + (h-w) * abs(cos(angles*pi/180)) + #h2 <- h + (w-h) * abs(sin(angles*pi/180)) - w3 <- convertWidth(unit(w2, "inch"), "npc") - h3 <- convertHeight(unit(h2, "inch"), "npc") + z2 <- xy.coords(xs2, ys2, recycle = TRUE) + xy2 <- toUserCoords(z2) - list(poly=polygonGrob(xs2, ys2, id=id, gp=rg$gp), - rect=rectGrob(rg$x, rg$y, width = w3, height=h3)) + list(poly=polygonGrob(unit(xy2$x, "native"), unit(xy2$y, "native"), id=id, gp=rg$gp)) + #list(poly=rectGrob(unit(x, "native"), unit(y, "native"), width = unit(w, "native"), height=unit(h, "native"), gp = rg$gp)) } .get_direction_angle <- function(co) { diff --git a/R/tm_layers_text.R b/R/tm_layers_text.R index db0e9d24..1e8d61bc 100644 --- a/R/tm_layers_text.R +++ b/R/tm_layers_text.R @@ -1,3 +1,54 @@ +#' @rdname tm_text +#' @name opt_tm_text +#' @export +opt_tm_text = function(points.only = "ifany", + just = "center", + along.lines = FALSE, + bg.padding = 0.4, + clustering = FALSE, + point.label = FALSE, + point.label.gap = 0, + point.label.method = "SANN", + remove.overlap = FALSE) { + list(trans.args = list(points.only = points.only, + along.lines = along.lines), + mapping.args = list(just = just, + along.lines = along.lines, + bg.padding = bg.padding, + clustering = clustering, + point.label = point.label, + point.label.gap = point.label.gap, + point.label.method = point.label.method, + remove.overlap = remove.overlap)) +} + + +#' @rdname tm_text +#' @name opt_tm_labels +#' @export +opt_tm_labels = function(points.only = "ifany", + just = "center", + along.lines = TRUE, + bg.padding = 0.4, + clustering = TRUE, + point.label = TRUE, + point.label.gap = 0.4, + point.label.method = "SANN", + remove.overlap = FALSE) { + list(trans.args = list(points.only = points.only, + along.lines = along.lines), + mapping.args = list(just = just, + along.lines = along.lines, + bg.padding = bg.padding, + clustering = clustering, + point.label = point.label, + point.label.gap = point.label.gap, + point.label.method = point.label.method, + remove.overlap = remove.overlap)) +} + + + #' Map layer: text #' #' Map layer that draws symbols Supported visual variables are: `text` @@ -51,6 +102,7 @@ #' groups can be switched on and off. Options: `"radio"` for radio buttons #' (meaning only one group can be shown), `"check"` for check boxes (so multiple groups can be shown), #' and `"none"` for no control (the group cannot be (de)selected). +#' @param options options passed on to the corresponding `opt_` function #' @param bgcol,bgcol.scale,bgcol.legend,bgcol.chart,bgcol.free Visual variable that determines #' the background color. See Details. #' @param bgcol_alpha,bgcol_alpha.scale,bgcol_alpha.legend,bgcol_alpha.chart,bgcol_alpha.free Visual variable that determines @@ -129,23 +181,12 @@ tm_text = function(text = tm_const(), zindex = NA, group = NA, group.control = "check", - points.only = "ifany", - just = "center", - along.lines = FALSE, - bg.padding = 0.4, - clustering = FALSE, - point.label = FALSE, - point.label.gap = 0, - point.label.method = "SANN", - remove.overlap = FALSE, + options = opt_tm_text(), ...) { #if (FALSE) { args = list(...) - trans.args = list(points.only = points.only, along.lines = along.lines) - mapping.args = list(clustering = clustering, point.label = point.label, remove.overlap = remove.overlap, point.label.gap = point.label.gap, point.label.method = point.label.method, just = just, bg.padding = bg.padding) - # dput(names(formals("tm_text"))) v3 = c("root", "clustering", "size.lim", "sizes.legend", "sizes.legend.labels", "sizes.legend.text", "n", "style", "style.args", @@ -249,7 +290,7 @@ tm_text = function(text = tm_const(), layer = "text", trans.fun = tmapTransCentroid, trans.aes = list(), - trans.args = trans.args, + trans.args = options$trans.args, trans.isglobal = FALSE, mapping.aes = list( text = tmapScale(aes = "text", @@ -337,7 +378,7 @@ tm_text = function(text = tm_const(), tpar = tmapTpar(), plot.order = plot.order, mapping.fun = "Text", - mapping.args = mapping.args, + mapping.args = options$mapping.args, zindex = zindex, group = group, group.control = group.control, @@ -408,12 +449,7 @@ tm_labels = function(text = tm_const(), zindex = NA, group = NA, group.control = "check", - points.only = "ifany", - along.lines = TRUE, - clustering = FALSE, - point.label = TRUE, - point.label.gap = 0.3, - remove.overlap = FALSE, + options = opt_tm_labels(), ...) { args = c(as.list(environment()), list(...)) tm = do.call(tm_text, args) diff --git a/R/tm_scale_.R b/R/tm_scale_.R index 70e76aaa..e24babc5 100644 --- a/R/tm_scale_.R +++ b/R/tm_scale_.R @@ -32,10 +32,19 @@ tm_scale = function(...) { structure(c(list(FUN = "tmapScaleAuto"), list(...)), class = c("tm_scale_auto", "tm_scale", "list")) } +#' Scales: as is +#' +#' Scales in tmap are configured by the family of functions with prefix `tm_scale`. +#' Such function should be used for the input of the `.scale` arguments in the +#' layer functions (e.g. `fill.scale` in [tm_polygons()]). +#' The function `tm_scale_asis()` is used to take data values as they are and use them as such for the visual variable. +#' +#' @param values.scale (generic scale argument) Scaling of the values. Only useful for size-related visual variables, such as `size` of [tm_symbols()] and `lwd` of [tm_lines()]. +#' @param value.neutral (generic scale argument) Value that can be considered neutral. This is used for legends of other visual variables of the same map layer. E.g. when both `fill` and `size` are used for [tm_symbols()] (using filled circles), the size legend items are filled with the `value.neutral` color from the `fill.scale` scale, and fill legend items are bubbles of size `value.neutral` from the `size.scale` scale. +#' @param ... Arguments caught (and not used) from the automatic function [tm_scale()] #' @export -#' @rdname tm_scale -tm_scale_asis = function(...) { - structure(c(list(FUN = "tmapScaleAsIs"), list(...)), class = c("tm_scale_asis", "tm_scale", "list")) +tm_scale_asis = function(values.scale = NA, value.neutral = NA, ...) { + structure(c(list(FUN = "tmapScaleAsIs"), c(list(values.scale = values.scale, value.neutral = value.neutral), list(...))), class = c("tm_scale_asis", "tm_scale", "list")) } #' @export diff --git a/R/tmapGrid_layers.R b/R/tmapGrid_layers.R index d5d59c74..64fca84d 100644 --- a/R/tmapGrid_layers.R +++ b/R/tmapGrid_layers.R @@ -332,11 +332,17 @@ tmapGridText = function(shpTM, dt, gp, bbx, facet_row, facet_col, facet_page, id args = list(...) rc_text = frc(facet_row, facet_col) + + if (("prop_angle" %in% names(shpTM))) { + args$point.label = FALSE + } res = select_sf(shpTM, dt) shp = res$shp dt = res$dt + + # specials non-vv (later on lost after gp_to_gpar) shadow = gp$shadow @@ -407,10 +413,12 @@ tmapGridText = function(shpTM, dt, gp, bbx, facet_row, facet_col, facet_page, id if (with_bg || args$remove.overlap) { tGH = vapply(grobTextList, function(grb) { + grb$rot = 0 convertHeight(grobHeight(grb), "inch", valueOnly = TRUE) }, FUN.VALUE = numeric(1), USE.NAMES = FALSE) * yIn tGW = vapply(grobTextList, function(grb) { + grb$rot = 0 convertWidth(grobWidth(grb), "inch", valueOnly = TRUE) }, FUN.VALUE = numeric(1), USE.NAMES = FALSE) * xIn @@ -426,10 +434,15 @@ tmapGridText = function(shpTM, dt, gp, bbx, facet_row, facet_col, facet_page, id tGH = unit(tGH + args$bg.padding * yIn * lineIn, "native") tGW = unit(tGW + args$bg.padding * xIn * lineIn, "native") - - grobTextBGList = mapply(function(x, y, w, h, b, a) { - rectGrob(x=x, y=y, width=w, height=h, gp=gpar(fill=b, alpha = a, col=NA)) - }, tGX, tGY, tGW, tGH, bgcol, bgcol_alpha, SIMPLIFY = FALSE, USE.NAMES = FALSE) + + grobTextBGList = mapply(function(x, y, w, h, b, a, rot) { + rect = rectGrob(x=x, y=y, width=w, height=h, gp=gpar(fill=b, alpha = a, col=NA)) + if (rot != 0) { + .rectGrob2pathGrob(rect, rot, bbx)$poly + } else { + rect + } + }, tGX, tGY, tGW, tGH, bgcol, bgcol_alpha, angle, SIMPLIFY = FALSE, USE.NAMES = FALSE) } else { grobTextBGList = NULL } diff --git a/R/tmapScaleRGB.R b/R/tmapScaleRGB.R index e6a37887..6763f2ac 100644 --- a/R/tmapScaleRGB.R +++ b/R/tmapScaleRGB.R @@ -46,36 +46,3 @@ tmapScaleRGB = function(x1, x2, x3, scale, legend, chart, o, aes, layer, layer_a list(vals = values, ids = ids, legend = legend, chart = chart, bypass_ord = bypass_ord) } } - - -tmapScaleAsIs = function(x1, scale, legend, chart, o, aes, layer, layer_args, sortRev, bypass_ord, submit_legend = TRUE) { - legend = list(title = NA, - nitems = 0, - labels = NA, - dvalues = NA, - vvalues = NA, - vneutral = NA, - na.show = NA, - scale = "AsIs", - show = FALSE) - - x1h = head(x1, 100) - check_values(layer, aes, x1h) - - - sfun = paste0("tmapValuesScale_", aes) - cfun = paste0("tmapValuesColorize_", aes) - - x2 = do.call(sfun, list(x = x1, scale = o$scale)) - values = do.call(cfun, list(x = x2, pc = o$pc)) - - if (submit_legend) { - if (bypass_ord) { - format_aes_results(values, legend = legend, chart = chart) - } else { - format_aes_results(values, ord = 1L, legend = legend, chart = chart) - } - } else { - list(vals = values, ids = 1L, legend = legend, chart = chart, bypass_ord = bypass_ord) - } -} \ No newline at end of file diff --git a/R/tmapScale_defaults.R b/R/tmapScale_defaults.R index f44e7894..00968fcf 100644 --- a/R/tmapScale_defaults.R +++ b/R/tmapScale_defaults.R @@ -69,7 +69,7 @@ tmapValuesCheck_area = function(x) { } tmapValuesCheck_text = function(x) { - is.character(x) + is.character(x) || is.factor(x) } tmapValuesCheck_fontface = function(x) { diff --git a/examples/tm_symbols.R b/examples/tm_symbols.R index 3a2ef7ca..3387c99f 100644 --- a/examples/tm_symbols.R +++ b/examples/tm_symbols.R @@ -1,15 +1,21 @@ -# load Africa country data -data(World, metro) +metroAfrica = sf::st_intersection(metro, World[World$continent == "Africa", ]) Africa = World[World$continent == "Africa", ] -metro_A = sf::st_intersection(metro, Africa) - -tm_shape(metro_A) + - tm_symbols() -tm_shape(Africa) + - tm_polygons() + - tm_shape(metro_A) + - tm_symbols(fill = "pop1950", size = "pop2030", size.scale = tm_scale(values.scale = 2)) +tm_shape(land) + + tm_raster("cover_cls", + col.scale = tm_scale(values = cols4all::c4a("brewer.pastel1")[c(3,7,7,2,6,1,2,2)]), + col.legend = tm_legend_hide()) + + tm_shape(rivers) + + tm_lines(lwd = "strokelwd", lwd.scale = tm_scale_asis(values.scale = .3), col = cols4all::c4a("brewer.pastel1")[2]) + + tm_shape(Africa, is.main = TRUE) + + tm_borders() + + tm_shape(metroAfrica) + + tm_symbols(fill = "red", shape = "pop2020", size = "pop2020", + size.scale = tm_scale_intervals(breaks = c(1, 2, 5, 10, 15, 20, 25) * 1e6, values.range = c(0.2,2)), + size.legend = tm_legend("Population in 2020"), + shape.scale = tm_scale_intervals(breaks = c(1, 2, 5, 10, 15, 20, 25) * 1e6, values = c(21, 23, 22, 21, 23, 22)), + shape.legend = tm_legend_combine("size")) + + tm_labels("name", options = opt_tm_labels(remove.overlap = FALSE)) ##### tmap v3 diff --git a/examples/tm_text.R b/examples/tm_text.R index 1310cb17..a45a0bc1 100644 --- a/examples/tm_text.R +++ b/examples/tm_text.R @@ -1,100 +1,40 @@ -# Need to be updated. The following is just to illustrate bgcol(_alpha) -tm_shape(World) + tm_polygons() + - tm_text("name", bgcol = "economy", bgcol_alpha = .5, shadow = TRUE) - -tm_shape(World) + - tm_text(text = "name", - size = .4, - bgcol = "economy") - -tm_shape(World) + - tm_text(text = "name", - size = .4, - bgcol = "economy", - bgcol.scale = tm_scale_categorical(values = cols4all::.P$hcl$cat$set2), - bgcol_alpha = "pop_est", - bgcol_alpha.scale = tm_scale_intervals(style = "kmeans")) - -tm_shape(metro) + - tm_text(text = "name", size = "pop2020", size.legend = tm_legend_hide()) - -## xymod -metro$initial = substr(metro$name,1,1) -metro$az = (match(metro$initial, LETTERS)-1) /25 - -tm_shape(metro) + - tm_dots("red") + - tm_text("initial", ymod = "az") - -# angle -tm_shape(World) + - tm_polygons() + -tm_shape(metro) + - tm_text(text = "name", size = "pop2020", - angle = -30, shadow = TRUE) +tm_shape(World, bbox = World) + + tm_text("name", size="pop_est", col="continent", + col.scale = tm_scale_categorical(values = "brewer.dark2"), + col.legend = tm_legend_hide(), + size.scale = tm_scale_continuous(values.scale = 4), + size.legend = tm_legend_hide()) metro$upside_down = ifelse(sf::st_coordinates(metro)[,2] < 0, 180, 0) tm_shape(metro) + tm_text(text = "name", size = "pop2020", - angle = "upside_down", size.legend = tm_legend_hide()) + angle = "upside_down", size.legend = tm_legend_hide()) + + tm_title_out("Cities in the Southern Hemisphere are printed upside down", position = tm_pos_out("center", "top", pos.v = "bottom")) DE = World[World$name == "Germany",] rivers_DE = sf::st_intersection(rivers, DE) -tm_shape(DE) + +tm_shape(DE, crs = 3035) + tm_polygons() + tm_shape(rivers_DE) + tm_lines(lwd = "strokelwd", lwd.scale = tm_scale_asis()) + - tm_labels("name") + tm_labels("name", bgcol = "grey85") metroAfrica = sf::st_intersection(metro, World[World$continent == "Africa", ]) - -# remove.overlap -tm_shape(metroAfrica) + - tm_text("name", bgcol = "yellow") + - tm_dots("red") - +Africa = World[World$continent == "Africa", ] + +tm_shape(land) + + tm_raster("cover_cls", + col.scale = tm_scale(values = cols4all::c4a("brewer.pastel1")[c(3,7,7,2,6,1,2,2)]), + col.legend = tm_legend_hide()) + +tm_shape(rivers) + + tm_lines(lwd = "strokelwd", lwd.scale = tm_scale_asis(values.scale = .3), col = cols4all::c4a("brewer.pastel1")[2]) + +tm_shape(Africa, is.main = TRUE) + + tm_borders() + tm_shape(metroAfrica) + - tm_text("name", bgcol = "yellow", remove.overlap = TRUE) + - tm_dots("red") - -# tm_labels uses a labeling algorithm that uses randomization -# (so rerunning this code may give different outcomes, unless set.seed is used) -tm_shape(metroAfrica) + - tm_labels("name", bgcol = "yellow") + - tm_dots("red") - -##### v3 examples - -current.mode <- tmap_mode("plot") - -data(World, metro) - -tm_shape(World) + - tm_text("name", size="AREA") - - -tm_shape(World) + - tm_text("name", size="pop_est", col="continent", palette="Dark2", - title.size = "Population", title.col="Continent") + - tm_legend(outside = TRUE) - -tmap_mode("view") - -\dontrun{ - require(tmaptools) - metro_aus <- crop_shape(metro, bb("Australia")) - - tm_shape(metro_aus) + - tm_dots() + - tm_text("name", just = "top") - - # alternative - tm_shape(metro_aus) + - tm_markers(text = "name") -} - -# restore current mode -tmap_mode(current.mode) - - + tm_symbols(fill = "red", shape = "pop2020", size = "pop2020", + size.scale = tm_scale_intervals(breaks = c(1, 2, 5, 10, 15, 20, 25) * 1e6, values.range = c(0.2,2)), + size.legend = tm_legend("Population in 2020"), + shape.scale = tm_scale_intervals(breaks = c(1, 2, 5, 10, 15, 20, 25) * 1e6, values = c(21, 23, 22, 21, 23, 22)), + shape.legend = tm_legend_combine("size")) + + tm_labels("name", options = opt_tm_labels(remove.overlap = FALSE)) diff --git a/man/tm_scale.Rd b/man/tm_scale.Rd index 58fa48a8..472ee8b2 100644 --- a/man/tm_scale.Rd +++ b/man/tm_scale.Rd @@ -2,12 +2,9 @@ % Please edit documentation in R/tm_scale_.R \name{tm_scale} \alias{tm_scale} -\alias{tm_scale_asis} \title{Scales: automatic scale} \usage{ tm_scale(...) - -tm_scale_asis(...) } \arguments{ \item{...}{arguments passed on to the applied scale function \verb{tm_scale_*()}} diff --git a/man/tm_symbols.Rd b/man/tm_symbols.Rd index cfc3f9da..4191f96b 100644 --- a/man/tm_symbols.Rd +++ b/man/tm_symbols.Rd @@ -270,18 +270,24 @@ so the \verb{*.free} argument requires only one logical value. } } \examples{ -# load Africa country data -data(World, metro) +metroAfrica = sf::st_intersection(metro, World[World$continent == "Africa", ]) Africa = World[World$continent == "Africa", ] -metro_A = sf::st_intersection(metro, Africa) - -tm_shape(metro_A) + - tm_symbols() -tm_shape(Africa) + - tm_polygons() + - tm_shape(metro_A) + - tm_symbols(fill = "pop1950", size = "pop2030", size.scale = tm_scale(values.scale = 2)) +tm_shape(land) + + tm_raster("cover_cls", + col.scale = tm_scale(values = cols4all::c4a("brewer.pastel1")[c(3,7,7,2,6,1,2,2)]), + col.legend = tm_legend_hide()) + + tm_shape(rivers) + + tm_lines(lwd = "strokelwd", lwd.scale = tm_scale_asis(values.scale = .3), col = cols4all::c4a("brewer.pastel1")[2]) + + tm_shape(Africa, is.main = TRUE) + + tm_borders() + + tm_shape(metroAfrica) + + tm_symbols(fill = "red", shape = "pop2020", size = "pop2020", + size.scale = tm_scale_intervals(breaks = c(1, 2, 5, 10, 15, 20, 25) * 1e6, values.range = c(0.2,2)), + size.legend = tm_legend("Population in 2020"), + shape.scale = tm_scale_intervals(breaks = c(1, 2, 5, 10, 15, 20, 25) * 1e6, values = c(21, 23, 22, 21, 23, 22)), + shape.legend = tm_legend_combine("size")) + + tm_labels("name", options = opt_tm_labels(remove.overlap = FALSE)) ##### tmap v3 diff --git a/man/tm_text.Rd b/man/tm_text.Rd index 0a27dec4..81c57996 100644 --- a/man/tm_text.Rd +++ b/man/tm_text.Rd @@ -1,10 +1,36 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/tm_layers_text.R -\name{tm_text} +\name{opt_tm_text} +\alias{opt_tm_text} +\alias{opt_tm_labels} \alias{tm_text} \alias{tm_labels} \title{Map layer: text} \usage{ +opt_tm_text( + points.only = "ifany", + just = "center", + along.lines = FALSE, + bg.padding = 0.4, + clustering = FALSE, + point.label = FALSE, + point.label.gap = 0, + point.label.method = "SANN", + remove.overlap = FALSE +) + +opt_tm_labels( + points.only = "ifany", + just = "center", + along.lines = TRUE, + bg.padding = 0.4, + clustering = TRUE, + point.label = TRUE, + point.label.gap = 0.4, + point.label.method = "SANN", + remove.overlap = FALSE +) + tm_text( text = tm_const(), text.scale = tm_scale(), @@ -62,15 +88,7 @@ tm_text( zindex = NA, group = NA, group.control = "check", - points.only = "ifany", - just = "center", - along.lines = FALSE, - bg.padding = 0.4, - clustering = FALSE, - point.label = FALSE, - point.label.gap = 0, - point.label.method = "SANN", - remove.overlap = FALSE, + options = opt_tm_text(), ... ) @@ -131,16 +149,29 @@ tm_labels( zindex = NA, group = NA, group.control = "check", - points.only = "ifany", - along.lines = TRUE, - clustering = FALSE, - point.label = TRUE, - point.label.gap = 0.3, - remove.overlap = FALSE, + options = opt_tm_labels(), ... ) } \arguments{ +\item{points.only}{should only point geometries of the shape object (defined in \code{\link[=tm_shape]{tm_shape()}}) be plotted? By default \code{"ifany"}, which means \code{TRUE} in case a geometry collection is specified.} + +\item{just}{justification of the text relative to the point coordinates. Either one of the following values: \code{"left"} , \code{"right"}, \code{"center"}, \code{"bottom"}, and \code{"top"}, or a vector of two values where first value specifies horizontal and the second value vertical justification. Besides the mentioned values, also numeric values between 0 and 1 can be used. 0 means left justification for the first value and bottom justification for the second value. Note that in view mode, only one value is used.} + +\item{along.lines}{logical that determines whether labels are rotated along the spatial lines. Only applicable if a spatial lines shape is used.} + +\item{bg.padding}{The padding of the background in terms of line heights.} + +\item{clustering}{value that determines whether the text labels are clustered in \code{"view"} mode. One of: \code{TRUE}, \code{FALSE}, or the output of \code{\link[leaflet:markerClusterOptions]{markerClusterOptions}}.} + +\item{point.label}{logical that determines whether the labels are placed automatically.} + +\item{point.label.gap}{numeric that determines the gap between the point and label} + +\item{point.label.method}{the optimization method, either \code{"SANN"} for simulated annealing (the default) or \code{"GA"} for a genetic algorithm.} + +\item{remove.overlap}{logical that determines whether the overlapping labels are removed} + \item{text, text.scale, text.legend, text.chart, text.free}{Visual variable that determines the text. See details.} @@ -188,23 +219,7 @@ groups can be switched on and off. Options: \code{"radio"} for radio buttons (meaning only one group can be shown), \code{"check"} for check boxes (so multiple groups can be shown), and \code{"none"} for no control (the group cannot be (de)selected).} -\item{points.only}{should only point geometries of the shape object (defined in \code{\link[=tm_shape]{tm_shape()}}) be plotted? By default \code{"ifany"}, which means \code{TRUE} in case a geometry collection is specified.} - -\item{just}{justification of the text relative to the point coordinates. Either one of the following values: \code{"left"} , \code{"right"}, \code{"center"}, \code{"bottom"}, and \code{"top"}, or a vector of two values where first value specifies horizontal and the second value vertical justification. Besides the mentioned values, also numeric values between 0 and 1 can be used. 0 means left justification for the first value and bottom justification for the second value. Note that in view mode, only one value is used.} - -\item{along.lines}{logical that determines whether labels are rotated along the spatial lines. Only applicable if a spatial lines shape is used.} - -\item{bg.padding}{The padding of the background in terms of line heights.} - -\item{clustering}{value that determines whether the text labels are clustered in \code{"view"} mode. One of: \code{TRUE}, \code{FALSE}, or the output of \code{\link[leaflet:markerClusterOptions]{markerClusterOptions}}.} - -\item{point.label}{logical that determines whether the labels are placed automatically.} - -\item{point.label.gap}{numeric that determines the gap between the point and label} - -\item{point.label.method}{the optimization method, either \code{"SANN"} for simulated annealing (the default) or \code{"GA"} for a genetic algorithm.} - -\item{remove.overlap}{logical that determines whether the overlapping labels are removed} +\item{options}{options passed on to the corresponding \verb{opt_} function} \item{...}{to catch deprecated arguments from version < 4.0} } @@ -239,104 +254,44 @@ own legend. For facet wraps and stacks (\code{\link[=tm_facets_wrap]{tm_facets_w there is only one facet dimension, so the \code{.free} argument requires only one logical value. } \examples{ -# Need to be updated. The following is just to illustrate bgcol(_alpha) -tm_shape(World) + tm_polygons() + - tm_text("name", bgcol = "economy", bgcol_alpha = .5, shadow = TRUE) - -tm_shape(World) + - tm_text(text = "name", - size = .4, - bgcol = "economy") - -tm_shape(World) + - tm_text(text = "name", - size = .4, - bgcol = "economy", - bgcol.scale = tm_scale_categorical(values = cols4all::.P$hcl$cat$set2), - bgcol_alpha = "pop_est", - bgcol_alpha.scale = tm_scale_intervals(style = "kmeans")) - -tm_shape(metro) + - tm_text(text = "name", size = "pop2020", size.legend = tm_legend_hide()) - -## xymod -metro$initial = substr(metro$name,1,1) -metro$az = (match(metro$initial, LETTERS)-1) /25 - -tm_shape(metro) + - tm_dots("red") + - tm_text("initial", ymod = "az") - -# angle -tm_shape(World) + - tm_polygons() + -tm_shape(metro) + - tm_text(text = "name", size = "pop2020", - angle = -30, shadow = TRUE) +tm_shape(World, bbox = World) + + tm_text("name", size="pop_est", col="continent", + col.scale = tm_scale_categorical(values = "brewer.dark2"), + col.legend = tm_legend_hide(), + size.scale = tm_scale_continuous(values.scale = 4), + size.legend = tm_legend_hide()) metro$upside_down = ifelse(sf::st_coordinates(metro)[,2] < 0, 180, 0) tm_shape(metro) + tm_text(text = "name", size = "pop2020", - angle = "upside_down", size.legend = tm_legend_hide()) + angle = "upside_down", size.legend = tm_legend_hide()) + + tm_title_out("Cities in the Southern Hemisphere are printed upside down", position = tm_pos_out("center", "top", pos.v = "bottom")) DE = World[World$name == "Germany",] rivers_DE = sf::st_intersection(rivers, DE) -tm_shape(DE) + +tm_shape(DE, crs = 3035) + tm_polygons() + tm_shape(rivers_DE) + tm_lines(lwd = "strokelwd", lwd.scale = tm_scale_asis()) + - tm_labels("name") + tm_labels("name", bgcol = "grey85") metroAfrica = sf::st_intersection(metro, World[World$continent == "Africa", ]) - -# remove.overlap -tm_shape(metroAfrica) + - tm_text("name", bgcol = "yellow") + - tm_dots("red") - +Africa = World[World$continent == "Africa", ] + +tm_shape(land) + + tm_raster("cover_cls", + col.scale = tm_scale(values = cols4all::c4a("brewer.pastel1")[c(3,7,7,2,6,1,2,2)]), + col.legend = tm_legend_hide()) + +tm_shape(rivers) + + tm_lines(lwd = "strokelwd", lwd.scale = tm_scale_asis(values.scale = .3), col = cols4all::c4a("brewer.pastel1")[2]) + +tm_shape(Africa, is.main = TRUE) + + tm_borders() + tm_shape(metroAfrica) + - tm_text("name", bgcol = "yellow", remove.overlap = TRUE) + - tm_dots("red") - -# tm_labels uses a labeling algorithm that uses randomization -# (so rerunning this code may give different outcomes, unless set.seed is used) -tm_shape(metroAfrica) + - tm_labels("name", bgcol = "yellow") + - tm_dots("red") - -##### v3 examples - -current.mode <- tmap_mode("plot") - -data(World, metro) - -tm_shape(World) + - tm_text("name", size="AREA") - - -tm_shape(World) + - tm_text("name", size="pop_est", col="continent", palette="Dark2", - title.size = "Population", title.col="Continent") + - tm_legend(outside = TRUE) - -tmap_mode("view") - -\dontrun{ - require(tmaptools) - metro_aus <- crop_shape(metro, bb("Australia")) - - tm_shape(metro_aus) + - tm_dots() + - tm_text("name", just = "top") - - # alternative - tm_shape(metro_aus) + - tm_markers(text = "name") -} - -# restore current mode -tmap_mode(current.mode) - - + tm_symbols(fill = "red", shape = "pop2020", size = "pop2020", + size.scale = tm_scale_intervals(breaks = c(1, 2, 5, 10, 15, 20, 25) * 1e6, values.range = c(0.2,2)), + size.legend = tm_legend("Population in 2020"), + shape.scale = tm_scale_intervals(breaks = c(1, 2, 5, 10, 15, 20, 25) * 1e6, values = c(21, 23, 22, 21, 23, 22)), + shape.legend = tm_legend_combine("size")) + + tm_labels("name", options = opt_tm_labels(remove.overlap = FALSE)) }