|
| 1 | +#' Cartesian coordinates with an aspect ratio approximating Mercator projection. |
| 2 | +#' |
| 3 | +#' The represenation of a portion of the earth, wich is approximately spherical, |
| 4 | +#' onto a flat 2D plane requires a projection. This is what |
| 5 | +#' \code{\link{coord_map}} does. These projections account for the fact that the |
| 6 | +#' actual length (in km) of one degree of longitude varies between the equator |
| 7 | +#' and the pole. Near the equator, the ratio between the lengths of one degree |
| 8 | +#' of latitude and one degree of longitude is approximately 1. Near the pole, it |
| 9 | +#' is tends towards infinity because the length of one degree of longitude tends |
| 10 | +#' towards 0. For regions that span only a few degrees and are not too close to |
| 11 | +#' the poles, setting the aspect ratio of the plot to the appropriate lat/lon |
| 12 | +#' ratio approximates the usual mercator projection. This is what |
| 13 | +#' \code{coord_quickmap} does. With \code{\link{coord_map}} all elements of the |
| 14 | +#' graphic have to be projected which is not the case here. So |
| 15 | +#' \code{\link{coord_quickmap}} has the advantage of being much faster, in |
| 16 | +#' particular for complex plots such as those using with |
| 17 | +#' \code{\link{geom_tile}}, at the expense of correctedness in the projection. |
| 18 | +#' |
| 19 | +#' @export |
| 20 | +#' @inheritParams coord_cartesian |
| 21 | +#' @examples |
| 22 | +#' # ensures that the ranges of axes are equal to the specified ratio by |
| 23 | +#' # adjusting the plot aspect ratio |
| 24 | +#' |
| 25 | +#' if (require("maps")) { |
| 26 | +#' # Create a lat-long dataframe from the maps package |
| 27 | +#' nz <- map_data("nz") |
| 28 | +#' # Prepare a plot of the map |
| 29 | +#' nzmap <- ggplot(nz, aes(x = long, y = lat, group = group)) + |
| 30 | +#' geom_polygon(fill = "white", colour = "black") |
| 31 | +#' |
| 32 | +#' # Plot it in cartesian coordinates |
| 33 | +#' nzmap |
| 34 | +#' # With correct mercator projection |
| 35 | +#' nzmap + coord_map() |
| 36 | +#' # With the aspect ratio approximation |
| 37 | +#' nzmap + coord_quickmap() |
| 38 | +#' } |
| 39 | +#' |
| 40 | +#' # Resize the plot to see that the specified aspect ratio is maintained |
| 41 | +coord_quickmap <- function(xlim = NULL, ylim = NULL) { |
| 42 | + coord(limits = list(x = xlim, y = ylim), |
| 43 | + subclass = c("quickmap", "cartesian")) |
| 44 | +} |
| 45 | + |
| 46 | +#' @export |
| 47 | +coord_aspect.quickmap <- function(coord, ranges) { |
| 48 | + # compute coordinates of center point of map |
| 49 | + x.center <- sum(ranges$x.range) / 2 |
| 50 | + y.center <- sum(ranges$y.range) / 2 |
| 51 | + |
| 52 | + # compute distance corresponding to 1 degree in either direction |
| 53 | + # from the center |
| 54 | + x.dist <- dist_central_angle(x.center + c(-0.5, 0.5), rep(y.center, 2)) |
| 55 | + y.dist <- dist_central_angle(rep(x.center, 2), y.center+c(-0.5, 0.5)) |
| 56 | + # NB: this makes the projection correct in the center of the plot and |
| 57 | + # increasingly less correct towards the edges. For regions of reasonnable |
| 58 | + # size, this seems to give better results than computing this ratio from |
| 59 | + # the total lat and lon span. |
| 60 | + |
| 61 | + # scale the plot with this aspect ratio |
| 62 | + ratio <- y.dist / x.dist |
| 63 | + |
| 64 | + diff(ranges$y.range) / diff(ranges$x.range) * ratio |
| 65 | +} |
0 commit comments