Skip to content

Quick approximation for map projections #922

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 25, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Collate:
'coord-map.r'
'coord-munch.r'
'coord-polar.r'
'coord-quickmap.R'
'coord-transform.r'
'facet-.r'
'facet-grid-.r'
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ S3method(coord_aspect,default)
S3method(coord_aspect,fixed)
S3method(coord_aspect,map)
S3method(coord_aspect,polar)
S3method(coord_aspect,quickmap)
S3method(coord_distance,cartesian)
S3method(coord_distance,map)
S3method(coord_distance,polar)
Expand Down Expand Up @@ -197,6 +198,7 @@ export(coord_fixed)
export(coord_flip)
export(coord_map)
export(coord_polar)
export(coord_quickmap)
export(coord_trans)
export(cut_interval)
export(cut_number)
Expand Down
7 changes: 7 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
ggplot2 0.9.3.1.99
----------------------------------------------------------------

* New coordinate system for small scale maps. `coord_quickmap()` computes and
sets the correct aspect ratio between one degree of latitude and one degree
of longitude at the centre of the plotted region. It does not perform full
fledged mapping projection as `coord_map()` does and therefore is much
faster. Yet, it gives a correct approximation for small scale maps (a few
degrees in either direction) at medium to low latitudes (@jiho, #922).

* Allow specifying only one of the limits in a scale and use the automatic
calculation of the other limit by passing NA to to the limit function,
`xlim()` or `ylim()` (@jimhester, #557).
Expand Down
65 changes: 65 additions & 0 deletions R/coord-quickmap.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#' Cartesian coordinates with an aspect ratio approximating Mercator projection.
#'
#' The represenation of a portion of the earth, wich is approximately spherical,
#' onto a flat 2D plane requires a projection. This is what
#' \code{\link{coord_map}} does. These projections account for the fact that the
#' actual length (in km) of one degree of longitude varies between the equator
#' and the pole. Near the equator, the ratio between the lengths of one degree
#' of latitude and one degree of longitude is approximately 1. Near the pole, it
#' is tends towards infinity because the length of one degree of longitude tends
#' towards 0. For regions that span only a few degrees and are not too close to
#' the poles, setting the aspect ratio of the plot to the appropriate lat/lon
#' ratio approximates the usual mercator projection. This is what
#' \code{coord_quickmap} does. With \code{\link{coord_map}} all elements of the
#' graphic have to be projected which is not the case here. So
#' \code{\link{coord_quickmap}} has the advantage of being much faster, in
#' particular for complex plots such as those using with
#' \code{\link{geom_tile}}, at the expense of correctedness in the projection.
#'
#' @export
#' @inheritParams coord_cartesian
#' @examples
#' # ensures that the ranges of axes are equal to the specified ratio by
#' # adjusting the plot aspect ratio
#'
#' if (require("maps")) {
#' # Create a lat-long dataframe from the maps package
#' nz <- map_data("nz")
#' # Prepare a plot of the map
#' nzmap <- ggplot(nz, aes(x = long, y = lat, group = group)) +
#' geom_polygon(fill = "white", colour = "black")
#'
#' # Plot it in cartesian coordinates
#' nzmap
#' # With correct mercator projection
#' nzmap + coord_map()
#' # With the aspect ratio approximation
#' nzmap + coord_quickmap()
#' }
#'
#' # Resize the plot to see that the specified aspect ratio is maintained
coord_quickmap <- function(xlim = NULL, ylim = NULL) {
coord(limits = list(x = xlim, y = ylim),
subclass = c("quickmap", "cartesian"))
}

#' @export
coord_aspect.quickmap <- function(coord, ranges) {
# compute coordinates of center point of map
x.center <- sum(ranges$x.range) / 2
y.center <- sum(ranges$y.range) / 2

# compute distance corresponding to 1 degree in either direction
# from the center
x.dist <- dist_central_angle(x.center + c(-0.5, 0.5), rep(y.center, 2))
y.dist <- dist_central_angle(rep(x.center, 2), y.center+c(-0.5, 0.5))
# NB: this makes the projection correct in the center of the plot and
# increasingly less correct towards the edges. For regions of reasonnable
# size, this seems to give better results than computing this ratio from
# the total lat and lon span.

# scale the plot with this aspect ratio
ratio <- y.dist / x.dist

diff(ranges$y.range) / diff(ranges$x.range) * ratio
}
51 changes: 51 additions & 0 deletions man/coord_quickmap.Rd
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
% Generated by roxygen2 (4.0.0): do not edit by hand
\name{coord_quickmap}
\alias{coord_quickmap}
\title{Cartesian coordinates with an aspect ratio approximating Mercator projection.}
\usage{
coord_quickmap(xlim = NULL, ylim = NULL)
}
\arguments{
\item{xlim}{limits for the x axis}

\item{ylim}{limits for the y axis}
}
\description{
The represenation of a portion of the earth, wich is approximately spherical,
onto a flat 2D plane requires a projection. This is what
\code{\link{coord_map}} does. These projections account for the fact that the
actual length (in km) of one degree of longitude varies between the equator
and the pole. Near the equator, the ratio between the lengths of one degree
of latitude and one degree of longitude is approximately 1. Near the pole, it
is tends towards infinity because the length of one degree of longitude tends
towards 0. For regions that span only a few degrees and are not too close to
the poles, setting the aspect ratio of the plot to the appropriate lat/lon
ratio approximates the usual mercator projection. This is what
\code{coord_quickmap} does. With \code{\link{coord_map}} all elements of the
graphic have to be projected which is not the case here. So
\code{\link{coord_quickmap}} has the advantage of being much faster, in
particular for complex plots such as those using with
\code{\link{geom_tile}}, at the expense of correctedness in the projection.
}
\examples{
# ensures that the ranges of axes are equal to the specified ratio by
# adjusting the plot aspect ratio

if (require("maps")) {
# Create a lat-long dataframe from the maps package
nz <- map_data("nz")
# Prepare a plot of the map
nzmap <- ggplot(nz, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", colour = "black")

# Plot it in cartesian coordinates
nzmap
# With correct mercator projection
nzmap + coord_map()
# With the aspect ratio approximation
nzmap + coord_quickmap()
}

# Resize the plot to see that the specified aspect ratio is maintained
}