Skip to content

Commit 4d26965

Browse files
committed
made webgl lines consistent, improved hitbox
1 parent c31075a commit 4d26965

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

R/tm_layers_lines.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ tm_lines = function(col = tm_const(),
277277
#' the interaction width. For example, \code{"times2"} doubles the
278278
#' clickable width.}
279279
#'
280-
#' \item{"auto"}{Automatically: \code{"pmax8"} by default. Only for large}
280+
#' \item{"auto"}{Automatically: \code{"pmax8"} by default if and only if interactive features are enabled (popup or hover) and lines are thin (median line width < 4) and there are less than 10000 features. Otherwise, \code{"none"} }
281281
#' }
282282
#'
283283
#' Adding a hitbox improves usability for thin lines but may reduce

R/tmapLeafletDataPlot_lines.R

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ tmapLeafletDataPlot.tm_data_lines = function(a, shpTM, dt, pdt, popup.format, hd
4747
a$hitbox
4848
}
4949

50+
5051
k = nrow(dt)
5152
if (hitbox == "none") {
5253
opt1 = leaflet::pathOptions(interactive = interactive, pane = pane, lineCap = gp$lineend, lineJoin = gp$linejoin)
@@ -58,6 +59,7 @@ tmapLeafletDataPlot.tm_data_lines = function(a, shpTM, dt, pdt, popup.format, hd
5859
opt2 = leaflet::pathOptions(interactive = interactive, pane = pane, lineCap = gp$lineend, lineJoin = gp$linejoin)
5960
idt = (if (is.null(idt))rep(dt$tmapID__, 2) else rep(idt, 2)) |>
6061
submit_labels("lines", pane, group)
62+
hb = parse_hitbox(hitbox)
6163
}
6264

6365

@@ -77,26 +79,28 @@ tmapLeafletDataPlot.tm_data_lines = function(a, shpTM, dt, pdt, popup.format, hd
7779

7880
if (hitbox == "none") {
7981
lf %>%
80-
lf %>%
8182
leafgl::addGlPolylines(
8283
data = shp3,
8384
color = gp3$col,
8485
opacity = gp3$col_alpha[1],
85-
weight = gp3$lwd[1]/4,
86+
weight = lwd_to_leafgl(gp3$lwd[1]),
8687
pane = pane,
8788
group = group,
8889
layerId = idt,
8990
label = hdt,
9091
popup= popups) %>%
9192
assign_lf(facet_row, facet_col, facet_page)
9293
} else {
94+
weights = gp3$lwd + hb$plus
95+
if (hb$pmax != 0) weights = pmax(weights, hb$pmax)
96+
9397
lf %>%
9498
# Fast WebGL rendering
9599
leafgl::addGlPolylines(
96100
data = shp3,
97101
color = gp3$col,
98102
opacity = gp3$col_alpha[1],
99-
weight = gp3$lwd[1] / 4,
103+
weight = lwd_to_leafgl(gp3$lwd[1]),
100104
pane = pane,
101105
group = group,
102106
popup = NULL,
@@ -107,7 +111,7 @@ tmapLeafletDataPlot.tm_data_lines = function(a, shpTM, dt, pdt, popup.format, hd
107111
leaflet::addPolylines(
108112
data = shp3,
109113
opacity = 0,
110-
weight = max(gp3$lwd / 4, 4),
114+
weight = weights,
111115
group = group,
112116
layerId = idt[(k+1):(2*k)],
113117
label = hdt,
@@ -129,11 +133,14 @@ tmapLeafletDataPlot.tm_data_lines = function(a, shpTM, dt, pdt, popup.format, hd
129133
opacity = gp$col_alpha,
130134
weight = gp$lwd,
131135
group = group,
132-
options = opt,
136+
options = opt1,
133137
dashArray = lty2dash(gp$lty, gp$lwd),
134138
popup = popups) %>%
135139
assign_lf(facet_row, facet_col, facet_page)
136140
} else {
141+
weights = gp$lwd + hb$plus
142+
if (hb$pmax != 0) weights = pmax(weights, hb$pmax)
143+
137144
lf %>%
138145
# Visible styled layer (no popup here)
139146
leaflet::addPolylines(
@@ -155,7 +162,7 @@ tmapLeafletDataPlot.tm_data_lines = function(a, shpTM, dt, pdt, popup.format, hd
155162
popup = popups,
156163
options = opt2,
157164
opacity = 0,
158-
weight = pmax(gp$lwd, 8),
165+
weight = weights,
159166
group = group
160167
) %>%
161168

@@ -179,3 +186,38 @@ tmapLeafletDataPlot.tm_data_iso = function(a, shpTM, dt, pdt, popup.format, hdt,
179186
NextMethod()
180187
}
181188

189+
parse_hitbox <- function(hitbox) {
190+
191+
# defaults
192+
plus <- 0
193+
pmax_ <- 0
194+
195+
if (is.null(hitbox) || hitbox == "none") {
196+
return(list(plus = 0, pmax = 0))
197+
}
198+
199+
# extract plus
200+
m_plus <- regexpr("plus[0-9]+", hitbox)
201+
if (m_plus > 0) {
202+
plus <- as.numeric(sub("plus", "", regmatches(hitbox, m_plus)))
203+
}
204+
205+
# extract pmax
206+
m_pmax <- regexpr("pmax[0-9]+", hitbox)
207+
if (m_pmax > 0) {
208+
pmax_ <- as.numeric(sub("pmax", "", regmatches(hitbox, m_pmax)))
209+
}
210+
211+
list(plus = plus, pmax = pmax_)
212+
}
213+
214+
lwd_to_leafgl <- function(lwd) {
215+
# empirical formula, based on observations: 1 (very small), 2 (2/8), 3 (3/6), 4 (4/4), 6 (6/3.5), 8 (8/3), 16 (16/8)
216+
ifelse(lwd <= 4,
217+
lwd / 2^(4 - log2(lwd)),
218+
ifelse(lwd > 8,
219+
lwd / 3,
220+
lwd / (6 - log2(lwd))
221+
))
222+
}
223+

0 commit comments

Comments
 (0)