Skip to content

Commit

Permalink
Update web page
Browse files Browse the repository at this point in the history
  • Loading branch information
MikkoVihtakari committed Nov 21, 2023
1 parent e47a8d2 commit 2d5128e
Show file tree
Hide file tree
Showing 110 changed files with 729 additions and 494 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: ggOceanMaps
Type: Package
Title: Plot Data on Oceanographic Maps using 'ggplot2'
Version: 2.1.11
Version: 2.1.12
Date: 2023-11-08
Authors@R: c(person("Mikko", "Vihtakari", email = "mikko.vihtakari@hi.no",
role = c("aut", "cre"),
Expand Down
19 changes: 14 additions & 5 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
# ggOceanMaps 2.2 (development version on GitHub)

- Fix an issue with certain bathy.style abbreviations
- qmap arguments did not match those of basemap: add bathy.alpha and downsample arguments to qmap
- Fix an [issue](https://stackoverflow.com/questions/60684049/creating-a-interactive-map-on-r-using-plotly) when trying to plot basemaps using `plotly::ggplotly()`
* Add tests better explaining wrongly specified arguments
* Update the user manual
* Fix an issue with certain `bathy.style` abbreviations
* qmap arguments did not match those of basemap: add `bathy.alpha` and `downsample` arguments to qmap
* Fix an [issue](https://stackoverflow.com/questions/60684049/creating-a-interactive-map-on-r-using-plotly) when trying to plot basemaps using `plotly::ggplotly()`
* Fix an issue with . in file path
* Fix an issue when plotting singular points
* Fix `basemap(c(-180, 180, -90, 90))` case and turn off automatic rotation when crossing the anti-meridian. A message is shown instead.
* Turn off `expand` in `ggplot2::coord_sf()` to avoid an error when having map border at 0 meridian.
* Fix a case where data argument produced too wide boundaries
* `expand.factor` should work now as designed
* Fix an error in `dist2land(binary = TRUE)`

# ggOceanMaps 2.1
# ggOceanMaps 2.1.1

* Fix a bug in bathy.style wording.
* Add [`get_depth()`](https://mikkovihtakari.github.io/ggOceanMaps/reference/get_depth.html) function.
* Fix a critical issue with downloads failing on Windows.
* Add detailed land shapes of Europe. Can be used by `basemap(shapefiles = "Europe")`

# ggOceanMaps 2.0
# ggOceanMaps 2.0.0

* Full [sf](https://r-spatial.github.io/sf/) integration. Old GIS packages for R and ggspatial dependencies removed. Since this change required rewriting of most functions, new bugs have almost certainly been introduced.
* Bathymetry system redesigned (see [this](https://mikkovihtakari.github.io/ggOceanMaps/articles/new-features.html))
Expand Down
14 changes: 12 additions & 2 deletions R/basemap.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
#' @param bathy.alpha Transparency parameter for the bathymetry fill color. See \link[ggplot2]{scale_alpha}.
#' @param base_size Base size parameter for ggplot. See \link[ggplot2]{ggtheme}.
#' @param projection.grid Logical indicating whether the coordinate grid should show projected coordinates instead of decimal degree values. Useful to define limits for large maps in polar regions.
#' @param expand.factor Expansion factor for map limits with the \code{data} argument. Can be used to zoom in and out automatically limited maps. Defaults to 1.1. Set to \code{NULL} to ignore.
#' @param expand.factor Expansion factor for map limits. Can be used to zoom in (decrease the value under 1) and out (increase the value over 1) automatically (\code{data}) limited maps. Defaults to 1, which means that outermost data points are located at the boundaries of the plotting region.
#' @param verbose Logical indicating whether information about the projection and guessed column names should be returned as messages. Set to \code{FALSE} to make the function silent.
#' @return Returns a \link[ggplot2]{ggplot} map, which can be assigned to an object and modified as any ggplot object.
#' @details The function uses \link[ggplot2:ggplot2-package]{ggplot2}, \link[sf:sf]{sf}, \link[stars:st_as_stars]{stars} and spatial files to plot maps of the world's oceans.
#'
#' \strong{Limits}
#'
#' If the limits are in decimal degrees, the longitude limits (\code{[1:2]}) specify the start and end segments of corresponding angular lines that should reside inside the map area. The longitude limits are defined \strong{counter-clockwise}. The latitude limits \code{[3:4]} define the parallels that should reside inside the limited region given the longitude segments. Note that the actual limited region becomes wider than the polygon defined by the coordinates (shown in Examples). Using \code{data} to limit the map expands the map all around the data points to make them fit into the map. If the limits are given as projected coordinates or as decimal degrees for maps with -60 < latitude < 60, limit elements represent lines encompassing the map area in cartesian space.
#' If the limits are in decimal degrees, the longitude limits (\code{[1:2]}) specify the start and end segments of corresponding angular lines that should reside inside the map area. The longitude limits are defined \strong{counter-clockwise}. The latitude limits \code{[3:4]} define the parallels that should reside inside the limited region given the longitude segments. Note that the actual limited region becomes wider than the polygon defined by the coordinates (shown in Examples). Using \code{data} to limit the map, making the points barely fit into the map. The \code{expand.factor} argument can be used to adjust the space between map borders and points. If the limits are given as projected coordinates or as decimal degrees for maps with -60 < latitude < 60, limit elements represent lines encompassing the map area in cartesian space.
#'
#' \strong{Projections}
#'
Expand Down Expand Up @@ -251,6 +251,16 @@ basemap <- function(x = NULL, limits = NULL, data = NULL, shapefiles = NULL, crs
message("The rotate argument cannot be used with custom crs. Turning rotate to FALSE.")
}

if(!is.null(data)) {
if(!inherits(data, "data.frame")) stop("The data argument has to be a data.frame, tibble or data.table")
if(nrow(data) == 0) stop("There are no rows in data.")
}

if(!is.null(limits)) {
if(!length(limits) %in% c(1,4)) stop("The limits argument has to be numeric vector of length 1 or 4. See Arguments.")
if(!inherits(limits, c("numeric", "integer"))) stop("The limits argument has to be a numeric vector. See Arguments.")
}

###########
# Data ####

Expand Down
238 changes: 162 additions & 76 deletions R/basemap_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -171,45 +171,6 @@ basemap_data_define_shapefiles <- function(limits = NULL, data = NULL, shapefile

shapefiles <- load_map_data(shapefiles)

# if(!is.na(shapefiles$path) &
# any(sapply(
# shapefiles[names(shapefiles) %in% c("land", "glacier", "bathy")],
# function(k) !grepl("::", k) & !is.null(k)))
# ) {
#
# ## Predifined shapefile case
#
# tmp <- load_map_data(x = shapefiles)
#
# shapefiles <- stats::setNames(lapply(seq_along(shapefiles), function(i) {
# test <- which(names(tmp) %in% shapefiles[[i]])
#
# if(length(test) != 1) {
# shapefiles[[i]]
# } else {
# if(names(shapefiles)[i] == "glacier" & !glaciers) {
# NULL
# } else if(names(shapefiles)[i] == "bathy" & !bathymetry) {
# NULL
# } else {
# tmp[[test]]
# }
# }
# }), names(shapefiles))
# }

# if(is.character(shapefiles$land)) {
# shapefiles$land <- eval(parse(text = shapefiles$land))
# }
#
# if(is.character(shapefiles$glacier)) {
# shapefiles$glacier <- eval(parse(text = shapefiles$glacier))
# }
#
# if(is.character(shapefiles$bathy)) {
# shapefiles$bathy <- eval(parse(text = shapefiles$bathy))
# }

if(any(sapply(shapefiles, function(k)
inherits(k, c("SpatialPolygons", "SpatialPolygonsDataFrame"))))) {
shapefiles <- lapply(shapefiles, function(k) {
Expand Down Expand Up @@ -266,15 +227,15 @@ basemap_data_define_shapefiles <- function(limits = NULL, data = NULL, shapefile
if(length(clip_shape) == 4) {
limits <- stats::setNames(clip_shape, c("xmin", "xmax", "ymin", "ymax"))

if(!sf::st_is_longlat(crs)){
clip_shape <- sf::st_as_sfc(
sf::st_bbox(limits, crs = crs)
)
limits <- sf::st_bbox(
sf::st_transform(
clip_shape, crs = 4326))[c("xmin", "xmax", "ymin", "ymax")]
}
#if(!sf::st_is_longlat(crs)){
clip_shape <- sf::st_as_sfc(
sf::st_bbox(limits, crs = crs)
)

limits <- sf::st_bbox(
sf::st_transform(
clip_shape, crs = 4326))[c("xmin", "xmax", "ymin", "ymax")]
#}

} else {
limits <- clip_shape
Expand Down Expand Up @@ -403,9 +364,11 @@ basemap_data_define_shapefiles <- function(limits = NULL, data = NULL, shapefile

if(is.null(shapefiles)) {

# if(rotate) {

limits <- sf::st_bbox(sf::st_transform(data, 4326))[c("xmin", "xmax", "ymin", "ymax")]
if(sf::st_is_longlat(data)) {
limits <- sf::st_bbox(data)[c("xmin", "xmax", "ymin", "ymax")]
} else {
limits <- sf::st_bbox(sf::st_transform(data, 4326))[c("xmin", "xmax", "ymin", "ymax")]
}

if(diff(limits[1:2]) == 0) {
limits[1:2] <- c(limits[1]-0.01, limits[2]+0.01)
Expand Down Expand Up @@ -655,7 +618,7 @@ basemap_data_crop <- function(x, bathymetry = FALSE, glaciers = FALSE, crs = NUL
x$shapefiles$land <- landBoundary$shapefile
x$clip_limits <- landBoundary$boundary

if(glaciers) {
if(!is.null(x$shapefiles$glacier)) {
if(!is.null(crs)) { # this hack is required for custom crs. Couldn't come up with a better solution
x$shapefiles$glacier <-
sf::st_transform(
Expand Down Expand Up @@ -715,8 +678,13 @@ basemap_data_crop <- function(x, bathymetry = FALSE, glaciers = FALSE, crs = NUL
}

if(!x$polarMap) {
x$limits <-
sf::st_bbox(sf::st_transform(sf::st_as_sf(x$clip_limits), 4236))[c("xmin", "xmax", "ymin", "ymax")]
if(sf::st_is_longlat(x$clip_limits)) {
x$limits <-
sf::st_bbox(sf::st_as_sf(x$clip_limits))[c("xmin", "xmax", "ymin", "ymax")]
} else {
x$limits <-
sf::st_bbox(sf::st_transform(sf::st_as_sf(x$clip_limits), 4236))[c("xmin", "xmax", "ymin", "ymax")]
}
}

map_limits <- sf::st_bbox(x$clip_limits)[c("xmin", "xmax", "ymin", "ymax")]
Expand All @@ -735,26 +703,50 @@ basemap_define_grid_lines <- function(x, lon.interval = NULL, lat.interval = NUL
## Define intervals if not specified

if(is.null(lat.interval)) {

if(x$polarMap) {
latDist <- 90 - abs(x$decLimits)

lat.interval <-
ifelse(latDist >= 30, 10,
ifelse(latDist >= 15, 5,
ifelse(latDist >= 10, 4,
ifelse(latDist >= 6, 3,
ifelse(latDist > 4, 2, 1)
))))
} else {
lat.breaks <- ggplot2::waiver()
limits <- sf::st_bbox(sf::st_transform(x$limit_shape, 4326))[c("xmin", "xmax", "ymin", "ymax")]

latDist <- abs(diff(round(limits)[3:4]))
}
lat.interval <-
ifelse(latDist >= 90, 20,
ifelse(latDist >= 30, 10,
ifelse(latDist >= 15, 5,
ifelse(latDist >= 10, 4,
ifelse(latDist >= 6, 3,
ifelse(latDist > 4, 2, 1)
)))))
}

if(is.null(lon.interval)) {

if(x$polarMap) {
lon.interval <- 45
} else {
lon.breaks <- ggplot2::waiver()
limits <- sf::st_bbox(sf::st_transform(x$limit_shape, 4326))[c("xmin", "xmax", "ymin", "ymax")]

if(diff(limits[1:2]) > 350) {
lonDist <- 360
} else {
tmp <- dd_to_deg(round(x$decLimits)[1:2])

if(tmp[1] > tmp[2]) {
lonDist <- 360 - tmp[1] + tmp[2]
} else {
lonDist <- tmp[2] - tmp[1]
}
}

lon.interval <-
ifelse(lonDist > 180, 45,
ifelse(lonDist > 90, 30,
ifelse(lonDist >= 40, 10,
ifelse(lonDist > 10, 5,
ifelse(lonDist > 4, 2, 1)
))))
}
}

Expand Down Expand Up @@ -802,19 +794,16 @@ basemap_define_grid_lines <- function(x, lon.interval = NULL, lat.interval = NUL

} else {

if(!is.null(lat.interval)) {
limits <- sf::st_bbox(sf::st_transform(x$limit_shape, 4326))[c("xmin", "xmax", "ymin", "ymax")]
minLat <- min(limits[3:4])
minLat <- ifelse(minLat < 0, -90, round_any(minLat, 10, floor))
maxLat <- max(limits[3:4])
maxLat <- ifelse(maxLat > 0, 90, round_any(maxLat, 10, ceiling))
lat.breaks <- seq(minLat, maxLat, lat.interval)
}
limits <- sf::st_bbox(sf::st_transform(x$limit_shape, 4326))[c("xmin", "xmax", "ymin", "ymax")]

if(!is.null(lon.interval)) {
lon.breaks <- unique(c(seq(0, 180, lon.interval), seq(-180, 0, lon.interval)))
}
minLat <- min(limits[3:4])
maxLat <- max(limits[3:4])

minLat <- ifelse(minLat < 0, -90, round_any(minLat, 10, floor))
maxLat <- ifelse(maxLat > 0, 90, round_any(maxLat, 10, ceiling))

lat.breaks <- seq(minLat, maxLat, lat.interval)
lon.breaks <- unique(c(seq(0, 180, lon.interval), seq(-180, 0, lon.interval)))
mapGrid <- list(lon.breaks = lon.breaks, lat.breaks = lat.breaks)
}

Expand All @@ -824,4 +813,101 @@ basemap_define_grid_lines <- function(x, lon.interval = NULL, lat.interval = NUL
limit_shape = x$limit_shape, map_limits = x$map_limits,
crs = x$crs, mapGrid = mapGrid)

}
}

## Cleaner version but does not produce grid line
# basemap_define_grid_lines <- function(x, lon.interval = NULL, lat.interval = NULL) {
#
# ## Define intervals if not specified
#
# if(is.null(lat.interval)) {
# if(x$polarMap) {
# latDist <- 90 - abs(x$decLimits)
#
# lat.interval <-
# ifelse(latDist >= 30, 10,
# ifelse(latDist >= 15, 5,
# ifelse(latDist >= 10, 4,
# ifelse(latDist >= 6, 3,
# ifelse(latDist > 4, 2, 1)
# ))))
# } else {
# lat.breaks <- ggplot2::waiver()
# }
# }
#
# if(is.null(lon.interval)) {
# if(x$polarMap) {
# lon.interval <- 45
# } else {
# lon.breaks <- ggplot2::waiver()
# }
# }
#
# ## Define the grid lines based on intervals
#
# if(x$polarMap) {
#
# poleLat <- ifelse(x$decLimits > 0, 90, -90)
#
# LonGridLines <- data.frame(
# id = rep(1:(360/lon.interval), each = 2),
# lon = rep(seq(-135, 180, lon.interval), each = 2),
# lat = rep(c(poleLat, x$decLimits), 360/lon.interval))
#
# LonGridLines <-
# sf::st_sfc(sf::st_multilinestring(
# x = lapply(unique(LonGridLines$id), function(i) {
# sf::st_linestring(as.matrix(LonGridLines[LonGridLines$id == i, 2:3]))
# })
# ), crs = 4326)
#
# LatLimitLine <- data.frame(lon = seq(-180, 180, 1), lat = x$decLimits)
#
# LatGridLines <-
# sign(x$decLimits) * seq(from = round(abs(x$decLimits)) + lat.interval,
# to = abs(poleLat) - lat.interval, by = lat.interval)
# LatGridLines <- LatGridLines[LatGridLines != x$decLimits]
# LatGridLines <-
# data.frame(lon = rep(seq(-180, 180, 1), length(LatGridLines)),
# lat = rep(LatGridLines, each = nrow(LatLimitLine)))
#
# LatGridLines <- sf::st_sfc(sf::st_multilinestring(
# lapply(unique(LatGridLines$lat), function(k) {
# sf::st_linestring(as.matrix(LatGridLines[LatGridLines$lat == k,]))
# })
# ), crs = 4326)
#
# LatLimitLine <-
# sf::st_sfc(
# sf::st_linestring(
# as.matrix(LatLimitLine)
# ), crs = 4326)
#
# mapGrid <- list(lon.grid.lines = LonGridLines, lat.grid.lines = LatGridLines, lat.limit.line = LatLimitLine)
#
# } else {
#
# if(!is.null(lat.interval)) {
# limits <- sf::st_bbox(sf::st_transform(x$limit_shape, 4326))[c("xmin", "xmax", "ymin", "ymax")]
# minLat <- min(limits[3:4])
# minLat <- ifelse(minLat < 0, -90, round_any(minLat, 10, floor))
# maxLat <- max(limits[3:4])
# maxLat <- ifelse(maxLat > 0, 90, round_any(maxLat, 10, ceiling))
# lat.breaks <- seq(minLat, maxLat, lat.interval)
# }
#
# if(!is.null(lon.interval)) {
# lon.breaks <- unique(c(seq(0, 180, lon.interval), seq(-180, 0, lon.interval)))
# }
#
# mapGrid <- list(lon.breaks = lon.breaks, lat.breaks = lat.breaks)
# }
#
# # Return ###
#
# list(shapefiles = x$shapefiles, polarMap = x$polarMap, decLimits = x$decLimits,
# limit_shape = x$limit_shape, map_limits = x$map_limits,
# crs = x$crs, mapGrid = mapGrid)
#
# }
Loading

0 comments on commit 2d5128e

Please sign in to comment.