There are a lot of problems in your code, so I suggest you try the simplified case first. In particular, the breakdown calculation was problematic. Try it,
library(ggplot2) library(proto) library(grid) GeomManythings <- ggproto( "GeomManythings", Geom, setup_data = function(self, data, params) { data <- ggproto_parent(Geom, self)$setup_data(data, params) data }, draw_group = function(data, panel_scales, coord) { n <- nrow(data) if (n <= 2) return(grid::nullGrob()) # polygon hull for all points hull_df <- data[chull(data[,c("x", "y")]), ] hull_grob <- GeomPolygon$draw_panel(hull_df, panel_scales, coord) # polygon hull for subset subset_of_x <- data[data$x > 0 & data$y > 0 ,] hull_of_subset_df <-subset_of_x[chull(subset_of_x[,c("x", "y")]),] hull_of_subset_df$fill <- "red" # testing hull_of_subset_grob <- GeomPolygon$draw_panel(hull_of_subset_df, panel_scales, coord) coords <- coord$transform(data, panel_scales) pg <- pointsGrob(x=mean(coords$x), y=mean(coords$y), default.units = "npc", gp=gpar(col="green", cex=3)) ggplot2:::ggname("geom_mypolygon", grobTree(hull_grob, hull_of_subset_grob, pg)) }, required_aes = c("x", "y"), draw_key = draw_key_polygon, default_aes = aes( colour = "grey20", fill = "grey50", size = 0.5, linetype = 1, alpha = 0.5 ) ) geom_manythings <- function(mapping = NULL, data = NULL, stat = "identity", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ...) { layer( geom = GeomManythings, mapping = mapping, data = data, stat = stat, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...) ) } set.seed(9) n <- 20 d <- data.frame(x = rnorm(n), y = rnorm(n)) ggplot(d, aes(x, y)) + geom_manythings()+ geom_point()

(disclaimer: I didnโt try to write a geoma after 5 years, so I donโt know how this works today)