I am trying to create a new geometry for ggplot
as described here, while adapting it to deal with Simple Features objects.
As an example, let's take the same exercise of plotting the convex hull of a set of points. Thus, I wrote a new geom_envelope()
function borrowing elements from geom_sf()
and a corresponding GeomEnvelope
ggproto
object that performs the computation overriding the draw_group()
method (since I want a single polygon for the full set of points).
However, I must be missing something, since I can't get the polygon plotted. I've been trying for a while but I either get errors or nothing plotted.
library(sf); library(ggplot2); library(dplyr)
Npts <- 10
pts <- matrix(runif(2*Npts), ncol = 2) %>%
st_multipoint() %>%
st_sfc() %>%
st_cast("POINT") %>%
st_sf()
GeomEnvelope <- ggproto(
"GeomEnvelope", GeomSf,
required_aes = "geometry",
default_aes = aes(
shape = NULL,
colour = "grey20",
fill = "white",
size = NULL,
linetype = 1,
alpha = 0.5,
stroke = 0.5
),
draw_key = draw_key_polygon,
draw_group = function(data, panel_params, coord) {
n <- nrow(data)
if (n <= 2) return(grid::nullGrob())
gp <- gpar(
colour = data$colour,
size = data$size,
linetype = data$linetype,
fill = alpha(data$fill, data$alpha),
group = data$group,
stringsAsFactors = FALSE
)
geometry <- sf::st_convex_hull(st_combine(sf::st_as_sf(data)))
sf::st_as_grob(geometry, pch = data$shape, gp = gp)
}
)
geom_envelope <- function(
mapping = aes(),
data = NULL,
position = "identity",
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE,
...) {
if (!is.null(data) && ggplot2:::is_sf(data)) {
geometry_col <- attr(data, "sf_column")
}
else {
geometry_col <- "geometry"
}
if (is.null(mapping$geometry)) {
mapping$geometry <- as.name(geometry_col)
}
c(
layer(
geom = GeomEnvelope,
data = data,
mapping = mapping,
stat = "identity",
position = position,
show.legend = if (is.character(show.legend))
TRUE
else
show.legend,
inherit.aes = inherit.aes,
params = list(
na.rm = na.rm,
legend = if (is.character(show.legend))
show.legend
else
"polygon",
...
)
),
coord_sf(default = TRUE)
)
}
ggplot(pts) + geom_sf() + geom_envelope() + theme_bw()
Created on 2019-04-23 by the reprex package (v0.2.1)
draw_key = draw_key_polygon,
? The functiondraw_key_polygon()
signature requires data. On another note, please add comments in your code to show what the function or sub-functions are doing or meant to do.. It's difficult to parse it otherwise. – Bacillarydraw_key
from the tutorial on extending ggplot2. Actually, I borrowed most of other functions from somewhere else, not always with full understanding of their role. Thus the lack of comments. – Universalist