diff --git a/NEWS.md b/NEWS.md index 63e891124f..520dc1e6ee 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,8 +3,11 @@ * `geom_sf()` now respects `lineend`, `linejoin`, and `linemitre` parameters for lines and polygons (@alistaire47, #2826) +* `geom_hline()`, `geom_vline()`, and `geom_abline()` now work properly + with `coord_trans()` (@clauswilke, #2149, #2812). + * `benchplot()` now uses tidy evaluation (@dpseidel, #2699). - + * `fortify()` now displays a more informative error message for `grouped_df()` objects when dplyr is not installed (@jimhester, #2822). diff --git a/R/coord-.r b/R/coord-.r index ce60824963..541cd827d9 100644 --- a/R/coord-.r +++ b/R/coord-.r @@ -13,14 +13,22 @@ #' - `render_bg`: Renders background elements. #' - `render_axis_h`: Renders the horizontal axes. #' - `render_axis_v`: Renders the vertical axes. -#' - `range`: Returns the x and y ranges +#' - `range(panel_params)`: Extracts the panel range provided +#' in `panel_params` (created by `setup_panel_params()`, see below) and +#' back-transforms to data coordinates. This back-transformation is needed +#' for coords such as `coord_flip()`, `coord_polar()`, `coord_trans()` where +#' the range in the transformed coordinates differs from the range in the +#' untransformed coordinates. #' - `transform`: Transforms x and y coordinates. #' - `distance`: Calculates distance. #' - `is_linear`: Returns `TRUE` if the coordinate system is #' linear; `FALSE` otherwise. #' - `is_free`: Returns `TRUE` if the coordinate system supports free -#' positional scales. -#' - `setup_panel_params(data)`: +#' positional scales; `FALSE` otherwise. +#' - `setup_panel_params(scale_x, scale_y, params)`: Determines the appropriate +#' x and y ranges for each panel, and also calculates anything else needed to +#' render the panel and axes, such as tick positions and labels for major +#' and minor ticks. Returns all this information in a named list. #' - `setup_data(data, params)`: Allows the coordinate system to #' manipulate the plot data. Should return list of data frames. #' - `setup_layout(layout, params)`: Allows the coordinate @@ -73,8 +81,15 @@ Coord <- ggproto("Coord", ) }, + # transform range given in transformed coordinates + # back into range in given in (possibly scale-transformed) + # data coordinates range = function(panel_params) { - return(list(x = panel_params$x.range, y = panel_params$y.range)) + warning( + "range backtransformation not implemented in this coord; plot may be wrong.", + call. = FALSE + ) + list(x = panel_params$x.range, y = panel_params$y.range) }, setup_panel_params = function(scale_x, scale_y, params = list()) { diff --git a/R/coord-cartesian-.r b/R/coord-cartesian-.r index ee4bc4b16b..b162b6359f 100644 --- a/R/coord-cartesian-.r +++ b/R/coord-cartesian-.r @@ -83,6 +83,10 @@ CoordCartesian <- ggproto("CoordCartesian", Coord, dist_euclidean(x, y) / max_dist }, + range = function(panel_params) { + list(x = panel_params$x.range, y = panel_params$y.range) + }, + transform = function(data, panel_params) { rescale_x <- function(data) rescale(data, from = panel_params$x.range) rescale_y <- function(data) rescale(data, from = panel_params$y.range) diff --git a/R/coord-map.r b/R/coord-map.r index e3012453e3..a08d8a8e16 100644 --- a/R/coord-map.r +++ b/R/coord-map.r @@ -119,6 +119,11 @@ CoordMap <- ggproto("CoordMap", Coord, out }, + range = function(panel_params) { + # range is stored in data coordinates and doesn't have to be back-transformed + list(x = panel_params$x.range, y = panel_params$y.range) + }, + distance = function(x, y, panel_params) { max_dist <- dist_central_angle(panel_params$x.range, panel_params$y.range) dist_central_angle(x, y) / max_dist diff --git a/R/coord-transform.r b/R/coord-transform.r index 0b70f60ca6..efe04b167c 100644 --- a/R/coord-transform.r +++ b/R/coord-transform.r @@ -119,6 +119,13 @@ CoordTrans <- ggproto("CoordTrans", Coord, dist_euclidean(self$trans$x$transform(x), self$trans$y$transform(y)) / max_dist }, + range = function(self, panel_params) { + list( + x = self$trans$x$inverse(panel_params$x.range), + y = self$trans$y$inverse(panel_params$y.range) + ) + }, + transform = function(self, data, panel_params) { trans_x <- function(data) transform_value(self$trans$x, data, panel_params$x.range) trans_y <- function(data) transform_value(self$trans$y, data, panel_params$y.range) diff --git a/R/sf.R b/R/sf.R index 61d2a85413..e88fc733f8 100644 --- a/R/sf.R +++ b/R/sf.R @@ -361,6 +361,10 @@ CoordSf <- ggproto("CoordSf", CoordCartesian, ) }, + range = function(panel_params) { + list(x = panel_params$x_range, y = panel_params$y_range) + }, + # CoordSf enforces a fixed aspect ratio -> axes cannot be changed freely under faceting is_free = function() FALSE, diff --git a/man/ggplot2-ggproto.Rd b/man/ggplot2-ggproto.Rd index 01951ba8b8..32c3fe5cfc 100644 --- a/man/ggplot2-ggproto.Rd +++ b/man/ggplot2-ggproto.Rd @@ -201,14 +201,22 @@ object, you typically will want to implement one or more of the following: \item \code{render_bg}: Renders background elements. \item \code{render_axis_h}: Renders the horizontal axes. \item \code{render_axis_v}: Renders the vertical axes. -\item \code{range}: Returns the x and y ranges +\item \code{range(panel_params)}: Extracts the panel range provided +in \code{panel_params} (created by \code{setup_panel_params()}, see below) and +back-transforms to data coordinates. This back-transformation is needed +for coords such as \code{coord_flip()}, \code{coord_polar()}, \code{coord_trans()} where +the range in the transformed coordinates differs from the range in the +untransformed coordinates. \item \code{transform}: Transforms x and y coordinates. \item \code{distance}: Calculates distance. \item \code{is_linear}: Returns \code{TRUE} if the coordinate system is linear; \code{FALSE} otherwise. \item \code{is_free}: Returns \code{TRUE} if the coordinate system supports free -positional scales. -\item \code{setup_panel_params(data)}: +positional scales; \code{FALSE} otherwise. +\item \code{setup_panel_params(scale_x, scale_y, params)}: Determines the appropriate +x and y ranges for each panel, and also calculates anything else needed to +render the panel and axes, such as tick positions and labels for major +and minor ticks. Returns all this information in a named list. \item \code{setup_data(data, params)}: Allows the coordinate system to manipulate the plot data. Should return list of data frames. \item \code{setup_layout(layout, params)}: Allows the coordinate