Arrange text labels inside a polygon
polygon_label_fill(
sp,
labels,
color = "black",
border = NA,
ref_sp = NULL,
fontsize = 10,
cex = 1,
degrees = 0,
dither_cex = 0.04,
dither_color = 0.07,
dither_degrees = 0,
scale_width = -0.15,
apply_n_scale = TRUE,
buffer_w = 0,
buffer_h = 0,
label_method = c("hexagonal", "nonaligned", "regular", "random", "stratified",
"clustered"),
layout_degrees = -20,
draw_buffer = FALSE,
buffer_fill = "#FFFFFF77",
buffer_border = "red",
draw_points = FALSE,
draw_labels = TRUE,
seed = NULL,
plot_style = c("base", "gg", "none"),
verbose = FALSE,
...
)
object sp::SpatialPolygons
character
vector of labels, the length defines
the number of coordinate positions to return.
vector
of R compatible colors which defines the
color of each label.
vector
or NA
with colors to define the border around
each label.
object sp::SpatialPolygons
used as a reference to
compare the size of sp
when apply_n_scale=TRUE
. In general,
fewer labels are placed more toward the center; also in general,
this effect is applied less for smaller polygons.
numeric
value indicating the font size in points.
numeric
value used to resize all text labels by
multiplying the font size.
numeric
vector
indicating the angle in degrees
to rotate each text label, where positive values rotate
in clockwise direction.
numeric
or NULL
, where a numeric value
is applied to cex
in random fashion to provide some
visual heterogeneity in the cex
for item labels. When
dither_cex=0
or dither_cex=NULL
then no adjustment
is performed.
numeric
or NULL
, where a numeric value
is use to adjust each color
slightly lighter or darker
via jamba::makeColorDarker()
. The effect is to make adjacent
labels visibly different but in a subtle way.
numeric
or NULL
, where a numeric value
is used to adjust the text angle slightly more or less that
the degrees
value.
numeric
value or NULL
, where a numeric
value indicates the relative size of the polygon to use as
a buffer around the polygon, and should be given as
negative values. For example scale_width=-0.1
will create
a buffer at 10% the size of the polygon.
logical
indicating whether to adjust the
polygon buffer based upon the number of labels, specifically
so that few labels (1, 2, or 3 labels) have much higher buffer
and therefore are positioned more central inside the polygon.
numeric
width and height, respectively,
used for additional buffer inside each polygon. These values
are appropriate when the width of text label is known. The
buffer polygon derived from scale_width
and apply_n_scale
is moved left, right, up, down, and the intersection of these
operations is used with sp::spsample()
to define label
positions. In this way, labels should fit inside the original
polygon without overlapping the boundary. This function does
not define default values, because the actual text label width
is dependent upon the diplay device properties at the time
the plot is drawn, and this device may not even be open when
this function is called.
character
string indicating the layout type
used by sp::spsample()
.
logical
indicating whether the buffer polygon
should be drawn, intended for visual review of the processing.
color values used when draw_buffer=TRUE
.
logical
indicating whether to draw points at
each coordinate position, intended for visual review of the processing.
logical
indicating whether to draw text labels
which is performed using gridtext::richtext_grob()
inside
a base R plot.
numeric
or NULL
, where a numeric
value is
passed to set.seed()
to make the dither_cex
process reproducible.
Set seed=NULL
to disable this step.
character
string indicating the expected output
plot style: "base"
uses base R graphics, gridtext::richtext_grob()
;
"gg"
uses ggplot2
style; "none"
does not plot anything.
logical
indicating whether to print verbose output.
list
that contains: items_df
as a data.frame
of item
label coordinates; and g_labels
as output from
gridtext::richtext_grob()
whose coordinates are defined
as "native"
, or g_labels=NULL
when plot_style="gg"
;
scale_width
with the numeric
value used; and
sp_buffer
with the sp::SpatialPolygons
object representing
the buffer region used for item labels.
This function takes a vector of text labels, and will
arrange those labels to fill the inside of a polygon.
Currently the method uses sp::spsample()
which
has a few algorithms to generate point positions
inside a polygon, and these positions are used to
anchor text labels. Currently this method does no
overlap detection.
The primary method to avoid overlap is to use
label_method="hexagon"
and degrees=20
, since hexagonal
layout tends to have points at roughly 0 and 60 degrees
from one another, and 20 degree rotation tends to allow
text labels to nestle beside each other without much
overlap.
Other venndir label:
draw_gridtext_groups()
,
polygon_label_outside()
,
polygon_label_segment()
,
sp_polylabelr()
sp <- sp_ellipses(3, 3, xradius=1.2, yradius=3, rotation_degrees=15)
words <- jamba::unvigrep("[0-9]",
jamba::vigrep("[a-zA-Z]",
unique(unlist(
strsplit(as.character(packageDescription("venndir")),
'[", _()<>:;/\n\t.@&=]+')))));
words <- words[nchar(words) > 2];
plot(sp, col="gold", border="gold4", lwd=2);
polygon_label_fill(sp=sp,
degrees=-10,
labels=words,
dither_color=0.2,
color="red2",
cex=1.2)
plot(sp, col="gold", border="gold4", lwd=2);
polygon_label_fill(sp=sp,
degrees=0,
draw_buffer=FALSE,
layout_degrees=45/2,
buffer_w=0.4,
label_method="regular",
labels=jamba::mixedSort(words),
dither_color=0.2,
dither_cex=0.2,
dither_degrees=0,
color="red2",
cex=1.2)
# iterate various options for reducing label overlap
par("mfrow"=c(2, 4));
for (lm in c("hexagonal", "regular")) {
for (ld in c(0, -45/2, -30, -45)) {
plot(sp, col="gold", border="gold4", lwd=2);
id <- ifelse(ld == 0, -20,
ifelse(ld == -45, 15, 0));
polygon_label_fill(sp=sp,
degrees=id,
layout_degrees=ld,
buffer_w=0.4,
label_method=lm,
#labels=seq_along(words),
#labels=rep("word", length(words)),
labels=paste0("word", seq_along(words)),
dither_color=0,
dither_cex=0,
dither_degrees=0,
color="navy",
cex=0.7)
title(main=paste0("layout_degrees=",
format(ld, digits=2),
"\nlabel_method='", lm, "'",
"\ndegrees=", id));
}
}
par("mfrow"=c(1, 1));
plot(sp, col="gold", border="gold4", lwd=2);
polygon_label_fill(sp=sp,
degrees=-10,
scale_width=-0.3,
draw_buffer=TRUE,
labels=words, dither_color=0.2, color="red2", cex=1.2)
setlist <- make_venn_test(100, 3);
vo <- venndir(setlist, return_items=TRUE, font_cex=0.01, proportional=FALSE);
#> ## (18:06:55) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:9
#> overlap_set text x y vjust hjust halign rot padding r
#> 9 set_A&set_B&set_C 1 4.999814 5.248994 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 9 pt #262626FF 0.14 NA NA 1 1 pt
#> num
#> 9 9
#> ## (18:06:55) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:7
#> overlap_set text x y vjust hjust halign rot padding r r_unit
#> 7 set_A&set_B 8 4.999106 6.748495 0.5 0.5 0.5 0 0.03 0.03 pt
#> label_col fontsize border_col box_fill box_lty box_lwd padding_unit num
#> 7 #262626FF 0.14 NA NA 1 1 pt 7
#> ## (18:06:55) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:8
#> overlap_set text x y vjust hjust halign rot padding r r_unit
#> 8 set_A&set_C 7 3.773922 4.632696 0.5 0.5 0.5 0 0.03 0.03 pt
#> label_col fontsize border_col box_fill box_lty box_lwd padding_unit num
#> 8 #262626FF 0.14 NA NA 1 1 pt 8
#> ## (18:06:55) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:1
#> overlap_set text x y vjust hjust halign rot padding r
#> 1 set_A **set_A** 1.90869 6.955722 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 1 pt #262626FF 0.14 NA NA 1 2 pt
#> num
#> 1 1
#> ## (18:06:55) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:4
#> overlap_set text x y vjust hjust halign rot padding r r_unit
#> 4 set_A 16 3.019531 6.238855 0.5 0.5 0.5 0 0.03 0.03 pt
#> label_col fontsize border_col box_fill box_lty box_lwd padding_unit num
#> 4 #262626FF 0.14 NA NA 1 1 pt 4
#> ## (18:06:55) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:5
#> overlap_set text x y vjust hjust halign rot padding r r_unit
#> 5 set_B 7 6.980469 6.238855 0.5 0.5 0.5 0 0.03 0.03 pt
#> label_col fontsize border_col box_fill box_lty box_lwd padding_unit num
#> 5 #262626FF 0.14 NA NA 1 1 pt 5
#> ## (18:06:55) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:2
#> overlap_set text x y vjust hjust halign rot padding r
#> 2 set_B **set_B** 8.091055 6.956222 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 2 pt #262626FF 0.14 NA NA 1 2 pt
#> num
#> 2 2
#> ## (18:06:55) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:6
#> overlap_set text x y vjust hjust halign rot padding r r_unit
#> 6 set_C 7 5.002174 3.08082 0.5 0.5 0.5 0 0.03 0.03 pt
#> label_col fontsize border_col box_fill box_lty box_lwd padding_unit num
#> 6 #262626FF 0.14 NA NA 1 1 pt 6
#> ## (18:06:55) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:3
#> overlap_set text x y vjust hjust halign rot padding r
#> 3 set_C **set_C** 5.003101 1.700411 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 3 pt #262626FF 0.14 NA NA 1 2 pt
#> num
#> 3 3
# labels inside each venn overlap polygon
venn_spdf <- vo$venn_spdf;
label_df <- vo$label_df;
for (i in seq_len(nrow(venn_spdf))) {
j <- match(venn_spdf$label[i], label_df$overlap_set);
if (length(unlist(label_df[j,"items"])) > 0) {
polygon_label_fill(sp=venn_spdf[i,],
ref_sp=venn_spdf,
color=venn_spdf$border[i],
scale_width=-0.1,
draw_buffer=TRUE,
labels=unlist(label_df[j,"items"]));
}
}
# same example as above but using proportional circles
vo <- venndir(setlist, font_cex=0.01, proportional=TRUE);
#> ## (18:06:56) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:9
#> overlap_set text x y vjust hjust halign rot padding
#> 9 set_A&set_B&set_C 1 0.1564435 0.5133692 0.5 0.5 0.5 0 0.03
#> r r_unit label_col fontsize border_col box_fill box_lty box_lwd
#> 9 0.03 pt #262626FF 0.14 NA NA 1 1
#> padding_unit num
#> 9 pt 9
#> ## (18:06:56) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:7
#> overlap_set text x y vjust hjust halign rot padding r
#> 7 set_A&set_B 8 0.5991818 -1.205417 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 7 pt #262626FF 0.14 NA NA 1 1 pt
#> num
#> 7 7
#> ## (18:06:56) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:8
#> overlap_set text x y vjust hjust halign rot padding r
#> 8 set_A&set_C 7 -1.454183 1.014376 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 8 pt #262626FF 0.14 NA NA 1 1 pt
#> num
#> 8 8
#> ## (18:06:56) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:4
#> overlap_set text x y vjust hjust halign rot padding r
#> 4 set_A 16 -2.414462 -1.780493 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 4 pt #262626FF 0.14 NA NA 1 1 pt
#> num
#> 4 4
#> ## (18:06:56) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:1
#> overlap_set text x y vjust hjust halign rot padding r
#> 1 set_A **set_A** -4.163439 -2.986351 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 1 pt #262626FF 0.14 NA NA 1 2 pt
#> num
#> 1 1
#> ## (18:06:56) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:5
#> overlap_set text x y vjust hjust halign rot padding r
#> 5 set_B 7 2.844281 -0.8726355 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 5 pt #262626FF 0.14 NA NA 1 1 pt
#> num
#> 5 5
#> ## (18:06:56) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:2
#> overlap_set text x y vjust hjust halign rot padding r
#> 2 set_B **set_B** 4.116615 -1.123098 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 2 pt #262626FF 0.14 NA NA 1 2 pt
#> num
#> 2 2
#> ## (18:06:56) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:6
#> overlap_set text x y vjust hjust halign rot padding r
#> 6 set_C 7 -1.064277 3.172044 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 6 pt #262626FF 0.14 NA NA 1 1 pt
#> num
#> 6 6
#> ## (18:06:56) 07Jul2023: draw_gridtext_groups(): grob_group_roundrect(), k:3
#> overlap_set text x y vjust hjust halign rot padding r
#> 3 set_C **set_C** -1.380893 4.465791 0.5 0.5 0.5 0 0.03 0.03
#> r_unit label_col fontsize border_col box_fill box_lty box_lwd padding_unit
#> 3 pt #262626FF 0.14 NA NA 1 2 pt
#> num
#> 3 3
# labels inside each venn overlap polygon
venn_spdf <- vo$venn_spdf;
label_df <- vo$label_df;
for (i in seq_len(nrow(venn_spdf))) {
j <- match(venn_spdf$label[i], label_df$overlap_set);
if (length(unlist(label_df[j,"items"])) > 0) {
polygon_label_fill(sp=venn_spdf[i,],
ref_sp=venn_spdf,
color=venn_spdf$border[i],
scale_width=-0.1,
draw_buffer=TRUE,
labels=unlist(label_df[j,"items"]));
}
}