ggpolypath icon indicating copy to clipboard operation
ggpolypath copied to clipboard

Mapping of non-fill aesthetics and fill = NA are not properly mapped

Open paleolimbot opened this issue 8 years ago • 0 comments

Ok, for real this time. In ggspatial it is common to map alpha and col in addition to fill. Passing fill=NA results in zero polygons being drawn, and mapping col results in a single outline colour of the drawn polygon.

library(ggplot2)
library(ggpolypath)

# create example plot
p <- ggplot(maphome, aes(x = x_, y = y_, group = branch_, fill = factor(object_)))

# without fills, no polygons are drawn
p + geom_polypath(col = "black", fill = NA)
p + geom_polygon(col = "black", fill = NA)

# colors are also not properly mapped
p + geom_polypath(aes(col = factor(object_)), fill = "red")
p + geom_polygon(aes(col = factor(object_)), fill = "red")

# alpha is also not properly mapped
p + geom_polypath(aes(alpha = factor(object_)), fill = "red")
p + geom_polygon(aes(alpha = factor(object_)), fill = "red")

I believe the problem is here:

ggplot2:::ggname(
      "geom_holygon",
      do.call(grid::grobTree, lapply(split(munched, munched$fill), object_munch))
)

When fill=NA, these values are removed, and these polygons are removed. My (perhaps inelegant) solution is to use with(munched, paste(fill, colour, alpha, size, linetype)) to split munched.

groups <- with(munched, paste(fill, colour, alpha, size, linetype))

ggplot2:::ggname(
  "geom_holygon",
  do.call(grid::grobTree, lapply(split(munched, groups), object_munch))
)

This appears to work for all the cases I tested, using the code below:

GeomPolypath2 <- ggproto(
  "GeomPolypath",
  GeomPolygon,
  extra_params = c("na.rm", "rule"),
  draw_panel = function(data, scales, coordinates, rule) {
    n <- nrow(data)
    if (n == 1)
      return(zeroGrob())

    munched <- coord_munch(coordinates, data, scales)
    munched <- munched[order(munched$group), ]
    ## function to be applied to get a pathGrob for each "region"
    object_munch <- function(xmunch) {
      first_idx <- !duplicated(xmunch$group)
      first_rows <- xmunch[first_idx, ]
      grid::pathGrob(xmunch$x, xmunch$y, default.units = "native",
                     id = xmunch$group, rule = rule,
                     gp = grid::gpar(col = first_rows$colour,
                                     fill = alpha(first_rows$fill, first_rows$alpha),
                                     lwd = first_rows$size * .pt,
                                     lty = first_rows$linetype))
    }

    groups <- with(munched, paste(fill, colour, alpha, size, linetype))

    ggplot2:::ggname(
      "geom_holygon",
      do.call(grid::grobTree, lapply(split(munched, groups), object_munch))
    )
  }
)

geom_polypath2 <- function(...) {
  stat_identity(..., geom = GeomPolypath2, rule = "winding")
}

# without fills, no polygons are drawn
p + geom_polypath(col = "black", fill = NA)
p + geom_polypath2(col = "black", fill = NA)
p + geom_polygon(col = "black", fill = NA)

# colors are also not properly mapped
p + geom_polypath(aes(col = factor(object_)), fill = "red")
p + geom_polypath2(aes(col = factor(object_)), fill = "red")
p + geom_polygon(aes(col = factor(object_)), fill = "red")

# alpha is also not properly mapped
p + geom_polypath(aes(alpha = factor(object_)), fill = "red")
p + geom_polypath2(aes(alpha = factor(object_)), fill = "red")
p + geom_polygon(aes(alpha = factor(object_)), fill = "red")

paleolimbot avatar Mar 31 '17 19:03 paleolimbot