Commit dffb0540 authored by Andreas Tille's avatar Andreas Tille

New upstream version 0.7-7+dfsg

parent 7b7e8ace
Package: sf
Version: 0.7-6
Version: 0.7-7
Title: Simple Features for R
Authors@R:
c(person(given = "Edzer",
......@@ -50,7 +50,7 @@ Depends: methods, R (>= 3.3.0)
Imports: classInt (>= 0.2-1), DBI (>= 0.8), graphics, grDevices, grid,
magrittr, Rcpp (>= 0.12.18), stats, tools, units (>= 0.6-0),
utils
Suggests: blob, covr, dplyr (>= 0.8-0), ggplot2, knitr, lwgeom (>=
Suggests: blob, covr, dplyr (>= 0.8-3), ggplot2, knitr, lwgeom (>=
0.1-5), maps, maptools, mapview, microbenchmark, odbc, pillar,
pool, raster, rgdal, rgeos, rlang, rmarkdown, RPostgres (>=
1.1.0), RPostgreSQL, RSQLite, sp (>= 1.2-4), spatstat, stars
......@@ -71,7 +71,7 @@ Collate: 'RcppExports.R' 'init.R' 'crs.R' 'bbox.R' 'read.R' 'db.R'
'stars.R' 'crop.R' 'gdal_utils.R' 'nearest.R' 'normalize.R'
'deprecated.R'
NeedsCompilation: yes
Packaged: 2019-07-05 07:47:37 UTC; edzer
Packaged: 2019-07-22 14:08:52 UTC; edzer
Author: Edzer Pebesma [aut, cre] (<https://orcid.org/0000-0001-8049-7069>),
Roger Bivand [ctb] (<https://orcid.org/0000-0003-2392-6140>),
Etienne Racine [ctb],
......@@ -85,4 +85,4 @@ Author: Edzer Pebesma [aut, cre] (<https://orcid.org/0000-0001-8049-7069>),
Thomas Lin Pedersen [ctb]
Maintainer: Edzer Pebesma <edzer.pebesma@uni-muenster.de>
Repository: CRAN
Date/Publication: 2019-07-05 12:30:08 UTC
Date/Publication: 2019-07-24 10:30:02 UTC
This diff is collapsed.
# version 0.7-7
* `plot()` handles `POSIXct` values in legend
* constructor functions like `st_linestring()` check and break on `NA` coordinates; #1101
# version 0.7-6
* have examples of `st_write` write only to the temporary R session directory
# version 0.7-5
* `as(x, "Spatial")` now gives a proper error message on empty geometries; #1093
......
......@@ -101,8 +101,8 @@ CPL_get_layers <- function(datasource, options, do_count = FALSE) {
.Call('_sf_CPL_get_layers', PACKAGE = 'sf', datasource, options, do_count)
}
CPL_read_ogr <- function(datasource, layer, query, options, quiet, toTypeUser, fid_column_name, promote_to_multi = TRUE, int64_as_string = FALSE) {
.Call('_sf_CPL_read_ogr', PACKAGE = 'sf', datasource, layer, query, options, quiet, toTypeUser, fid_column_name, promote_to_multi, int64_as_string)
CPL_read_ogr <- function(datasource, layer, query, options, quiet, toTypeUser, fid_column_name, promote_to_multi = TRUE, int64_as_string = FALSE, dsn_exists = TRUE, dsn_isdb = FALSE) {
.Call('_sf_CPL_read_ogr', PACKAGE = 'sf', datasource, layer, query, options, quiet, toTypeUser, fid_column_name, promote_to_multi, int64_as_string, dsn_exists, dsn_isdb)
}
CPL_gdalinfo <- function(obj, options) {
......
......@@ -4,7 +4,7 @@
#' @param ... objects to bind; note that for the rbind and cbind methods, all objects have to be of class \code{sf}; see \link{dotsMethods}
#' @param deparse.level integer; see \link[base]{rbind}
#' @name bind
#' @details both \code{rbind} and \code{cbind} have non-standard method dispatch (see \link[base]{cbind}): the \code{rbind} or \code{cbind} method for \code{sf} objects is only called when all arguments to be binded are of class \code{sf}.
#' @details both \code{rbind} and \code{cbind} have non-standard method dispatch (see \link[base]{cbind}): the \code{rbind} or \code{cbind} method for \code{sf} objects is only called when all arguments to be binded are of class \code{sf}.
#' @export
#' @examples
#' crs = st_crs(3857)
......@@ -12,7 +12,7 @@
#' b = st_sf(a=1, geom = st_sfc(st_linestring(matrix(1:4,2))), crs = crs)
#' c = st_sf(a=4, geom = st_sfc(st_multilinestring(list(matrix(1:4,2)))), crs = crs)
#' rbind(a,b,c)
#' rbind(a,b)
#' rbind(a,b)
#' rbind(a,b)
#' rbind(b,c)
rbind.sf = function(..., deparse.level = 1) {
......@@ -27,7 +27,7 @@ rbind.sf = function(..., deparse.level = 1) {
ret = st_sf(rbind.data.frame(...), crs = crs0)
st_geometry(ret) = st_sfc(st_geometry(ret)) # might need to reclass to GEOMETRY
bb = do.call(rbind, lapply(dots, st_bbox))
bb = bb_wrap(c(min(bb[,1L], na.rm = TRUE), min(bb[,2L], na.rm = TRUE),
bb = bb_wrap(c(min(bb[,1L], na.rm = TRUE), min(bb[,2L], na.rm = TRUE),
max(bb[,3L], na.rm = TRUE), max(bb[,4L], na.rm = TRUE)))
attr(ret[[ attr(ret, "sf_column") ]], "bbox") = bb
ret
......@@ -59,6 +59,12 @@ cbind.sf = function(..., deparse.level = 1, sf_column_name = NULL) {
#' @export
#' @details \code{st_bind_cols} is deprecated; use \code{cbind} instead.
st_bind_cols = function(...) {
.Deprecated("cbind") # nocov
cbind.sf(...) # nocov
# nocov start
.Deprecated("cbind",
msg = paste0("Use 'cbind' instead when all arguments",
" to be binded are of class sf.\n",
"If you need to cbind a data.frame to an sf,",
" use 'st_sf' or 'dplyr::bind_cols' (see the examples)."))
cbind.sf(...)
# nocov end
}
......@@ -170,7 +170,9 @@ st_geos_binop = function(op, x, y, par = 0.0, pattern = NA_character_,
#' st_distance(p, p)
#' st_distance(p, p, by_element = TRUE)
#' @export
st_distance = function(x, y, ..., dist_fun, by_element = FALSE, which = "Euclidean", par = 0.0, tolerance = 0.0) {
st_distance = function(x, y, ..., dist_fun, by_element = FALSE,
which = ifelse(isTRUE(st_is_longlat(x)), "Great Circle", "Euclidean"),
par = 0.0, tolerance = 0.0) {
if (missing(y))
y = x
else
......@@ -185,6 +187,8 @@ st_distance = function(x, y, ..., dist_fun, by_element = FALSE, which = "Euclide
if (isTRUE(st_is_longlat(x))) {
if (! requireNamespace("lwgeom", quietly = TRUE))
stop("lwgeom required: install first?")
if (which != "Great Circle")
stop("for non-great circle distances, data should be projected; see st_transform()")
units(tolerance) = as_units("m")
if (by_element) {
crs = st_crs(x)
......
......@@ -102,12 +102,15 @@ plot.sf <- function(x, y, ..., main, pal = NULL, nbreaks = 10, breaks = "pretty"
if (logz)
values = log10(values)
if (is.character(breaks)) { # compute breaks from values:
n.unq = length(unique(na.omit(values)))
v0 = na.omit(as.numeric(values))
n.unq = length(unique(v0))
breaks = if (! all(is.na(values)) && n.unq > 1)
classInt::classIntervals(na.omit(values), min(nbreaks, n.unq),
classInt::classIntervals(v0, min(nbreaks, n.unq),
breaks, warnSmallN = FALSE)$brks
else
range(values, na.rm = TRUE) # lowest and highest!
if (inherits(values, "POSIXct"))
breaks = as.POSIXct(breaks, origin = as.POSIXct("1970-01-01"))
nbreaks = length(breaks) - 1
}
}
......@@ -152,8 +155,8 @@ plot.sf <- function(x, y, ..., main, pal = NULL, nbreaks = 10, breaks = "pretty"
if (is.list(values))
stop("plotting list-columns not supported") # nocov
if (inherits(values, "POSIXt"))
values = as.numeric(values)
# if (inherits(values, "POSIXt"))
# values = as.numeric(values)
if (is.character(values))
values = as.factor(values)
......@@ -175,15 +178,19 @@ plot.sf <- function(x, y, ..., main, pal = NULL, nbreaks = 10, breaks = "pretty"
pal
colors[as.numeric(values)]
} else {
values = as.numeric(values) # drop units, if any
if (! inherits(values, "POSIXt"))
values = as.numeric(values) # drop units, if any
if (is.character(breaks)) { # compute breaks from values:
n.unq = length(unique(na.omit(values)))
v0 = na.omit(as.numeric(values))
n.unq = length(unique(v0))
breaks = if (! all(is.na(values)) && n.unq > 1)
classInt::classIntervals(na.omit(values), min(nbreaks, n.unq),
classInt::classIntervals(v0, min(nbreaks, n.unq),
breaks, warnSmallN = FALSE)$brks
else
range(values, na.rm = TRUE) # lowest and highest!
}
if (inherits(values, "POSIXt"))
breaks = as.POSIXct(breaks, origin = as.POSIXct("1970-01-01"))
}
# this is necessary if breaks were specified either as character or as numeric
# "pretty" takes nbreaks as advice only:
nbreaks = length(breaks) - 1
......@@ -534,7 +541,7 @@ plot.sfg = function(x, ...) {
#'
plot_sf = function(x, xlim = NULL, ylim = NULL, asp = NA, axes = FALSE, bgc = par("bg"), ...,
xaxs, yaxs, lab, setParUsrBB = FALSE, bgMap = NULL, expandBB = c(0,0,0,0), graticule = NA_crs_,
col_graticule = 'grey') {
col_graticule = 'grey', border) {
# sp's bbox: matrix
# min max
......@@ -795,9 +802,9 @@ bb2merc = function(x, cls = "ggmap") { # return bbox in the appropriate "web mer
c(offset,offset,0,0))
for(i in seq_along(poly)) {
if (key.pos %in% c(1,3))
polygon(poly[[i]], c(0, 0, 1, 1) + offs, col=col[i], border=NA)
polygon(poly[[i]], c(0, 0, 1, 1) + offs, col = col[i], border = NA)
if (key.pos %in% c(2,4))
polygon(c(0, 0, 1, 1) + offs, poly[[i]], col=col[i], border=NA)
polygon(c(0, 0, 1, 1) + offs, poly[[i]], col = col[i], border = NA)
}
# box() now would draw around [0,1]:
......@@ -809,7 +816,9 @@ bb2merc = function(x, cls = "ggmap") { # return bbox in the appropriate "web mer
labels = if (logz)
parse(text = paste0("10^", at))
else
else if (inherits(breaks, "POSIXt"))
format(at)
else
TRUE
if (add.axis)
......
......@@ -61,6 +61,9 @@ set_utf8 = function(x) {
#' without warnings. \code{promote_to_multi} is handled on a per-geometry column
#' basis; \code{type} may be specified for each geometry column.
#'
#' Note that stray files in data source directories (such as \code{*.dbf}) may
#' lead to spurious errors that accompanying \code{*.shp} are missing.
#'
#' In case of problems reading shapefiles from USB drives on OSX, please see
#' \url{https://github.com/r-spatial/sf/issues/252}.
#'
......@@ -79,6 +82,7 @@ set_utf8 = function(x) {
#' contain a single layer, an object of class \code{sf_layers} is returned
#' with the layer names, each with their geometry type(s). Note that the
#' number of layers may also be zero.
#' @seealso \link{st_layers}, \link{st_drivers}
#' @examples
#' nc = st_read(system.file("shape/nc.shp", package="sf"))
#' summary(nc) # note that AREA was computed using Euclidian area on lon/lat degrees
......@@ -194,20 +198,23 @@ st_read.character = function(dsn, layer, ..., query = NA, options = NULL, quiet
character(0)
else
enc2utf8(layer)
if (length(dsn) == 1 && file.exists(dsn))
if (nchar(dsn) < 1) {
stop("`dsn` must point to a source, not an empty string.", call. = FALSE)
}
dsn_exists = file.exists(dsn)
dsn_isdb = is_db_driver(dsn)
if (length(dsn) == 1 && dsn_exists && !dsn_isdb)
dsn = enc2utf8(normalizePath(dsn))
if (length(promote_to_multi) > 1)
stop("`promote_to_multi' should have length one, and applies to all geometry columns")
x = CPL_read_ogr(dsn, layer, query, as.character(options), quiet, type, fid_column_name,
promote_to_multi, int64_as_string)
x = CPL_read_ogr(dsn, layer, query, as.character(options), quiet, type, fid_column_name,
promote_to_multi, int64_as_string, dsn_exists, dsn_isdb)
process_cpl_read_ogr(x, quiet, check_ring_dir = check_ring_dir,
stringsAsFactors = stringsAsFactors, geometry_column = geometry_column, ...)
}
#' @name st_read
#' @export
#' @details \code{read_sf} and \code{write_sf} are aliases for \code{st_read} and \code{st_write}, respectively, with some
......@@ -342,7 +349,7 @@ st_write.sfc = function(obj, dsn, layer, ...) {
st_write.sf = function(obj, dsn, layer = NULL, ...,
driver = guess_driver_can_write(dsn),
dataset_options = NULL, layer_options = NULL, quiet = FALSE, factorsAsCharacter = TRUE,
update = driver %in% db_drivers, delete_dsn = FALSE, delete_layer = FALSE,
update = driver %in% db_drivers, delete_dsn = FALSE, delete_layer = FALSE,
fid_column_name = NULL) {
if (missing(dsn))
......@@ -433,13 +440,17 @@ write_sf <- function(..., quiet = TRUE, delete_layer = TRUE) {
#' Get GDAL drivers
#'
#' Get a list of the available GDAL drivers
#' @param what character: "vector" or "raster", anything else will return all drivers.
#' @details The drivers available will depend on the installation of GDAL/OGR, and can vary; the \code{st_drivers()}
#' function shows which are available, and which may be written (but all are assumed to be readable). Note that stray
#' files in data source directories (such as *.dbf) may lead to spurious errors that accompanying *.shp are missing.
#' @return a \code{data.frame} with driver metadata
#' @details field \code{vsi} refers to the driver's capability to read/create datasets through the VSI*L API.
#' @param what character: `"vector"` or `"raster"`, anything else will return all
#' drivers.
#' @details The drivers available will depend on the installation of GDAL/OGR,
#' and can vary; the `st_drivers()` function shows all the drivers that are
#' readable, and which may be written. The field `vsi` refers to the driver's
#' capability to read/create datasets through the VSI*L API. [See GDAL website
#' for additional details on driver
#' support](https://gdal.org/drivers/vector/index.html).
#' @return A `data.frame` with driver metadata.
#' @export
#' @md
#' @examples
#' st_drivers()
st_drivers = function(what = "vector") {
......@@ -502,7 +513,7 @@ guess_driver = function(dsn) {
# find match: try extension first
drv = extension_map[tolower(tools::file_ext(dsn))]
if (any(grep(":", gsub(":[/\\]", "/", dsn))))
if (is_db_driver(dsn))
drv = prefix_map[tolower(strsplit(dsn, ":")[[1]][1])]
drv <- unlist(drv)
......@@ -514,6 +525,10 @@ guess_driver = function(dsn) {
drv
}
is_db_driver = function(dsn) {
any(grep(":", gsub(":[/\\]", "/", dsn)))
}
guess_driver_can_write = function(dns, drv = guess_driver(dns)) {
if(is.na(drv)) {
stop("Could not guess driver for ", dns, call. = FALSE)
......
......@@ -262,8 +262,14 @@ st_sf = function(..., agr = NA_agr_, row.names,
as.data.frame(x[-all_sfc_columns],
stringsAsFactors = stringsAsFactors, optional = TRUE))
for (i in seq_along(all_sfc_names))
df[[ all_sfc_names[i] ]] = st_sfc(x[[ all_sfc_columns[i] ]], check_ring_dir = check_ring_dir)
if (check_ring_dir) { # process:
for (i in seq_along(all_sfc_names))
df[[ all_sfc_names[i] ]] = st_sfc(x[[ all_sfc_columns[i] ]],
check_ring_dir = check_ring_dir)
} else { # copy:
for (i in seq_along(all_sfc_names))
df[[ all_sfc_names[i] ]] = x[[ all_sfc_columns[i] ]]
}
if (! missing(precision))
attr(df[[sfc_name]], "precision") = precision
......
......@@ -11,11 +11,12 @@ getClassDim = function(x, d, dim = "XYZ", type) {
else stop(paste(d, "is an illegal number of columns for a", type))
}
is_numeric_matrix = function(x)
stopifnot(is.numeric(x) && is.matrix(x))
valid_numeric_matrix = function(x) {
stopifnot(is.numeric(x), is.matrix(x), !anyNA(x))
}
Mtrx = function(x, dim = "XYZ", type) {
is_numeric_matrix(x)
valid_numeric_matrix(x)
structure(x, class = getClassDim(x, ncol(x), dim, type))
}
......@@ -26,7 +27,7 @@ MtrxSet = function(x, dim = "XYZ", type, needClosed = FALSE) {
nc = unique(vapply(x, ncol, 0L))
if (length(nc) != 1)
stop("matrices have unequal numbers of columns")
lapply(x, is_numeric_matrix)
lapply(x, valid_numeric_matrix)
NotClosed = function(y) any(y[1, ] != y[nrow(y), ])
if (needClosed && any(vapply(x, NotClosed, TRUE)))
stop("polygons not (all) closed")
......@@ -45,7 +46,7 @@ MtrxSetSet = function(x, dim = "XYZ", type, needClosed = FALSE) {
nc = unique(unlist(lapply(x, function(y) vapply(y, ncol, 0L))))
if (length(nc) != 1)
stop("matrices have unequal numbers of columns")
lapply(x, function(y) lapply(y, is_numeric_matrix))
lapply(x, function(y) lapply(y, valid_numeric_matrix))
NotClosed = function(y) any(y[1, ] != y[nrow(y), ])
if (needClosed && any(unlist(lapply(x, function(y) vapply(y, NotClosed, TRUE)))))
stop("polygons not (all) closed")
......@@ -213,7 +214,7 @@ head.sfg = function(x, n = 10L, ...) {
structure(head(unclass(x), n = n, ...), class = class(x))
}
#
#
get_start = function(x, n = 30) {
if (is.list(x)) # recurse into first element:
structure(lapply(x, get_start, n = n), class = class(x))
......
No preview for this file type
......@@ -4166,7 +4166,7 @@ GEOS_VERSION=`${GEOS_CONFIG} --version`
$as_echo "$as_me: GEOS: ${GEOS_VERSION}" >&6;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking GEOS version >= 3.4.0" >&5
$as_echo_n "checking GEOS version >= 3.4.0... " >&6; } # GDAL 2.0.1 requires GEOS 3.1.0
GEOS_VER_DOT=`echo $GEOS_VERSION | tr -d "."`
GEOS_VER_DOT=`echo $GEOS_VERSION | tr -d ".[:alpha:]"`
if test ${GEOS_VER_DOT} -lt 340 ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
......
......@@ -674,7 +674,7 @@ fi
GEOS_VERSION=`${GEOS_CONFIG} --version`
AC_MSG_NOTICE([GEOS: ${GEOS_VERSION}])
AC_MSG_CHECKING([GEOS version >= 3.4.0]) # GDAL 2.0.1 requires GEOS 3.1.0
GEOS_VER_DOT=`echo $GEOS_VERSION | tr -d "."`
GEOS_VER_DOT=`echo $GEOS_VERSION | tr -d ".[[:alpha:]]"`
if test ${GEOS_VER_DOT} -lt 340 ; then
AC_MSG_RESULT(no)
AC_MSG_ERROR([upgrade GEOS to 3.4.0 or later])
......
## ----echo=FALSE, include=FALSE-------------------------------------------
knitr::opts_chunk$set(collapse = TRUE)
mostly_off = Sys.getenv("USER") == "edzer"
## ------------------------------------------------------------------------
library(sf)
......@@ -68,42 +69,37 @@ plot(usa, graticule = g, key.pos = NULL, axes = TRUE,
## ------------------------------------------------------------------------
methods(st_as_grob)
## ---- eval=FALSE---------------------------------------------------------
# devtools::install_github("tidyverse/ggplot2")
## ------------------------------------------------------------------------
library(ggplot2)
if (utils::packageVersion("ggplot2") > "2.2.1")
ggplot() + geom_sf(data = usa)
ggplot() + geom_sf(data = usa)
## ------------------------------------------------------------------------
if (utils::packageVersion("ggplot2") > "2.2.1")
ggplot() + geom_sf(data = nc, aes(fill = BIR74)) + scale_y_continuous(breaks = 34:36)
ggplot() +
geom_sf(data = nc, aes(fill = BIR74)) +
scale_y_continuous(breaks = 34:36)
## ------------------------------------------------------------------------
library(dplyr)
library(tidyr)
nc2 <- nc %>% select(SID74, SID79, geom) %>% gather(VAR, SID, -geom)
if (utils::packageVersion("ggplot2") > "2.2.1")
ggplot() + geom_sf(data = nc2, aes(fill = SID)) + facet_wrap(~VAR, ncol = 1) +
scale_y_continuous(breaks = 34:36)
ggplot() +
geom_sf(data = nc2, aes(fill = SID)) +
facet_wrap(~VAR, ncol = 1) +
scale_y_continuous(breaks = 34:36)
## ------------------------------------------------------------------------
## ----eval=mostly_off-----------------------------------------------------
library(mapview)
if (Sys.getenv("USER") %in% c("edzer", "travis"))
mapview(nc["BIR74"], col.regions = sf.colors(10))
mapview(nc["BIR74"], col.regions = sf.colors(10))
## ------------------------------------------------------------------------
library(tmap)
qtm(nc)
## ------------------------------------------------------------------------
## ----eval=mostly_off-----------------------------------------------------
tmap_mode("view")
if (Sys.getenv("USER") != "CRAN")
tm_shape(nc) + tm_fill("BIR74", palette = sf.colors(5))
tm_shape(nc) + tm_fill("BIR74", palette = sf.colors(5))
## ------------------------------------------------------------------------
## ----eval=mostly_off-----------------------------------------------------
ttm()
if (Sys.getenv("USER") != "CRAN")
last_map()
last_map()
......@@ -15,6 +15,7 @@ vignette: >
```{r echo=FALSE, include=FALSE}
knitr::opts_chunk$set(collapse = TRUE)
mostly_off = Sys.getenv("USER") == "edzer"
```
This vignette describes the functions in `sf` that can help to plot
simple features. It tries to be complete about the plot methods
......@@ -161,23 +162,18 @@ which convert simple simple feature objects into `grob` ("graphics objects") obj
## ggplot2
The `ggplot2` version to be released after 2.2.1 (on CRAN), which currently has to be installed by
```{r, eval=FALSE}
devtools::install_github("tidyverse/ggplot2")
```
contains a geom specially for simple feature objects, with support for graticule white lines in the background using `sf::st_graticule`. Support is currently good for polygons; for lines or points your milage may vary.
```{r}
library(ggplot2)
if (utils::packageVersion("ggplot2") > "2.2.1")
ggplot() + geom_sf(data = usa)
ggplot() + geom_sf(data = usa)
```
polygons can be colored using `aes`:
```{r}
if (utils::packageVersion("ggplot2") > "2.2.1")
ggplot() + geom_sf(data = nc, aes(fill = BIR74)) + scale_y_continuous(breaks = 34:36)
ggplot() +
geom_sf(data = nc, aes(fill = BIR74)) +
scale_y_continuous(breaks = 34:36)
```
and sets of maps can be plotted as facet plots after rearranging the `sf` object, e.g. by
......@@ -185,19 +181,19 @@ and sets of maps can be plotted as facet plots after rearranging the `sf` object
library(dplyr)
library(tidyr)
nc2 <- nc %>% select(SID74, SID79, geom) %>% gather(VAR, SID, -geom)
if (utils::packageVersion("ggplot2") > "2.2.1")
ggplot() + geom_sf(data = nc2, aes(fill = SID)) + facet_wrap(~VAR, ncol = 1) +
scale_y_continuous(breaks = 34:36)
ggplot() +
geom_sf(data = nc2, aes(fill = SID)) +
facet_wrap(~VAR, ncol = 1) +
scale_y_continuous(breaks = 34:36)
```
## mapview
Package `mapview` creates interactive maps in html pages, using package `leaflet` as a work horse. Extensive examples are found [here](https://r-spatial.github.io/mapview/).
```{r}
```{r,eval=mostly_off}
library(mapview)
if (Sys.getenv("USER") %in% c("edzer", "travis"))
mapview(nc["BIR74"], col.regions = sf.colors(10))
mapview(nc["BIR74"], col.regions = sf.colors(10))
```
gives a map which is interactive: you can zoom and pan, and query features by clicking on them.
......@@ -212,16 +208,13 @@ qtm(nc)
```
`tmap` also has interactive leaflet maps:
```{r}
```{r,eval=mostly_off}
tmap_mode("view")
if (Sys.getenv("USER") != "CRAN")
tm_shape(nc) + tm_fill("BIR74", palette = sf.colors(5))
tm_shape(nc) + tm_fill("BIR74", palette = sf.colors(5))
```
replotting the last map in non-interactive mode is as simple as:
```{r}
```{r,eval=mostly_off}
ttm()
if (Sys.getenv("USER") != "CRAN")
last_map()
last_map()
```
......@@ -41,7 +41,7 @@ a = st_sf(a=1, geom = st_sfc(st_point(0:1)), crs = crs)
b = st_sf(a=1, geom = st_sfc(st_linestring(matrix(1:4,2))), crs = crs)
c = st_sf(a=4, geom = st_sfc(st_multilinestring(list(matrix(1:4,2)))), crs = crs)
rbind(a,b,c)
rbind(a,b)
rbind(a,b)
rbind(a,b)
rbind(b,c)
cbind(a,b,c) # warns
......
......@@ -12,7 +12,8 @@ st_area(x, ...)
st_length(x)
st_distance(x, y, ..., dist_fun, by_element = FALSE,
which = "Euclidean", par = 0, tolerance = 0)
which = ifelse(isTRUE(st_is_longlat(x)), "Great Circle", "Euclidean"),
par = 0, tolerance = 0)
}
\arguments{
\item{x}{object of class \code{sf}, \code{sfc} or \code{sfg}}
......
......@@ -58,7 +58,7 @@ get_key_pos(x, ...)
plot_sf(x, xlim = NULL, ylim = NULL, asp = NA, axes = FALSE,
bgc = par("bg"), ..., xaxs, yaxs, lab, setParUsrBB = FALSE,
bgMap = NULL, expandBB = c(0, 0, 0, 0), graticule = NA_crs_,
col_graticule = "grey")
col_graticule = "grey", border)
sf.colors(n = 10, cutoff.tails = c(0.35, 0.2), alpha = 1,
categorical = FALSE)
......
......@@ -7,20 +7,20 @@
st_drivers(what = "vector")
}
\arguments{
\item{what}{character: "vector" or "raster", anything else will return all drivers.}
\item{what}{character: \code{"vector"} or \code{"raster"}, anything else will return all
drivers.}
}
\value{
a \code{data.frame} with driver metadata
A \code{data.frame} with driver metadata.
}
\description{
Get a list of the available GDAL drivers
}
\details{
The drivers available will depend on the installation of GDAL/OGR, and can vary; the \code{st_drivers()}
function shows which are available, and which may be written (but all are assumed to be readable). Note that stray
files in data source directories (such as *.dbf) may lead to spurious errors that accompanying *.shp are missing.
field \code{vsi} refers to the driver's capability to read/create datasets through the VSI*L API.
The drivers available will depend on the installation of GDAL/OGR,
and can vary; the \code{st_drivers()} function shows all the drivers that are
readable, and which may be written. The field \code{vsi} refers to the driver's
capability to read/create datasets through the VSI*L API. \href{https://gdal.org/drivers/vector/index.html}{See GDAL website for additional details on driver support}.
}
\examples{
st_drivers()
......
......@@ -107,6 +107,9 @@ other way around (type=3), secondary rings from MULTIPOLYGONS may be dropped
without warnings. \code{promote_to_multi} is handled on a per-geometry column
basis; \code{type} may be specified for each geometry column.
Note that stray files in data source directories (such as \code{*.dbf}) may
lead to spurious errors that accompanying \code{*.shp} are missing.
In case of problems reading shapefiles from USB drives on OSX, please see
\url{https://github.com/r-spatial/sf/issues/252}.
......@@ -182,3 +185,6 @@ if (exists("conn") && !inherits(conn, "try-error")) {
}
}
}
\seealso{
\link{st_layers}, \link{st_drivers}
}
......@@ -289,8 +289,8 @@ BEGIN_RCPP
END_RCPP
}
// CPL_read_ogr
Rcpp::List CPL_read_ogr(Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer, Rcpp::CharacterVector query, Rcpp::CharacterVector options, bool quiet, Rcpp::NumericVector toTypeUser, Rcpp::CharacterVector fid_column_name, bool promote_to_multi, bool int64_as_string);
RcppExport SEXP _sf_CPL_read_ogr(SEXP datasourceSEXP, SEXP layerSEXP, SEXP querySEXP, SEXP optionsSEXP, SEXP quietSEXP, SEXP toTypeUserSEXP, SEXP fid_column_nameSEXP, SEXP promote_to_multiSEXP, SEXP int64_as_stringSEXP) {
Rcpp::List CPL_read_ogr(Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer, Rcpp::CharacterVector query, Rcpp::CharacterVector options, bool quiet, Rcpp::NumericVector toTypeUser, Rcpp::CharacterVector fid_column_name, bool promote_to_multi, bool int64_as_string, bool dsn_exists, bool dsn_isdb);
RcppExport SEXP _sf_CPL_read_ogr(SEXP datasourceSEXP, SEXP layerSEXP, SEXP querySEXP, SEXP optionsSEXP, SEXP quietSEXP, SEXP toTypeUserSEXP, SEXP fid_column_nameSEXP, SEXP promote_to_multiSEXP, SEXP int64_as_stringSEXP, SEXP dsn_existsSEXP, SEXP dsn_isdbSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
......@@ -303,7 +303,9 @@ BEGIN_RCPP
Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type fid_column_name(fid_column_nameSEXP);
Rcpp::traits::input_parameter< bool >::type promote_to_multi(promote_to_multiSEXP);
Rcpp::traits::input_parameter< bool >::type int64_as_string(int64_as_stringSEXP);
rcpp_result_gen = Rcpp::wrap(CPL_read_ogr(datasource, layer, query, options, quiet, toTypeUser, fid_column_name, promote_to_multi, int64_as_string));
Rcpp::traits::input_parameter< bool >::type dsn_exists(dsn_existsSEXP);
Rcpp::traits::input_parameter< bool >::type dsn_isdb(dsn_isdbSEXP);
rcpp_result_gen = Rcpp::wrap(CPL_read_ogr(datasource, layer, query, options, quiet, toTypeUser, fid_column_name, promote_to_multi, int64_as_string, dsn_exists, dsn_isdb));
return rcpp_result_gen;
END_RCPP
}
......@@ -1069,7 +1071,7 @@ static const R_CallMethodDef CallEntries[] = {
{"_sf_CPL_gdal_segmentize", (DL_FUNC) &_sf_CPL_gdal_segmentize, 2},
{"_sf_CPL_gdal_linestring_sample", (DL_FUNC) &_sf_CPL_gdal_linestring_sample, 2},
{"_sf_CPL_get_layers", (DL_FUNC) &_sf_CPL_get_layers, 3},
{"_sf_CPL_read_ogr", (DL_FUNC) &_sf_CPL_read_ogr, 9},
{"_sf_CPL_read_ogr", (DL_FUNC) &_sf_CPL_read_ogr, 11},
{"_sf_CPL_gdalinfo", (DL_FUNC) &_sf_CPL_gdalinfo, 2},
{"_sf_CPL_gdalwarp", (DL_FUNC) &_sf_CPL_gdalwarp, 3},
{"_sf_CPL_gdalrasterize", (DL_FUNC) &_sf_CPL_gdalrasterize, 3},
......
......@@ -3,12 +3,13 @@
#include <ogrsf_frmts.h>
#define RCPP_DEFAULT_INCLUDE_CALL false
#include "Rcpp.h"
#include "gdal_sf_pkg.h"
#include "gdal_read.h"
Rcpp::List allocate_out_list(OGRFeatureDefn *poFDefn, int n_features, bool int64_as_string,
Rcpp::List allocate_out_list(OGRFeatureDefn *poFDefn, int n_features, bool int64_as_string,
Rcpp::CharacterVector fid_column) {
if (fid_column.size() > 1)
......@@ -190,7 +191,7 @@ Rcpp::List CPL_get_layers(Rcpp::CharacterVector datasource, Rcpp::CharacterVecto
return out;
}
Rcpp::List sf_from_ogrlayer(OGRLayer *poLayer, bool quiet, bool int64_as_string,
Rcpp::List sf_from_ogrlayer(OGRLayer *poLayer, bool quiet, bool int64_as_string,
Rcpp::NumericVector toTypeUser, Rcpp::CharacterVector fid_column, bool promote_to_multi = true) {
double n_d = (double) poLayer->GetFeatureCount();
......@@ -475,20 +476,31 @@ Rcpp::List sf_from_ogrlayer(OGRLayer *poLayer, bool quiet, bool int64_as_string,
}
// [[Rcpp::export]]
Rcpp::List CPL_read_ogr(Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer,
Rcpp::List CPL_read_ogr(Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer,
Rcpp::CharacterVector query,
Rcpp::CharacterVector options, bool quiet, Rcpp::NumericVector toTypeUser,
Rcpp::CharacterVector fid_column_name,
bool promote_to_multi = true, bool int64_as_string = false) {
bool promote_to_multi = true, bool int64_as_string = false,
bool dsn_exists = true,
bool dsn_isdb = false) {
// adapted from the OGR tutorial @ www.gdal.org
std::vector <char *> open_options = create_options(options, quiet);
GDALDataset *poDS;
poDS = (GDALDataset *) GDALOpenEx( datasource[0], GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL,
poDS = (GDALDataset *) GDALOpenEx( datasource[0], GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL,
open_options.data(), NULL );
if( poDS == NULL ) {
Rcpp::Rcout << "Cannot open data source " << datasource[0] << std::endl;
Rcpp::stop("Open failed.\n");
// could not open dsn
if( dsn_isdb ) {
Rcpp::stop("Cannot open %s; Check connection parameters.", datasource);
}
if( dsn_exists ) {
Rcpp::stop("Cannot open %s; %s %s",
datasource,
"The source could be corrupt or not supported.",
"See `st_drivers()` for a list of supported formats.");
}
Rcpp::stop("Cannot open %s; The file doesn't seem to exist.", datasource);
}
if (layer.size() == 0) { // no layer specified
......@@ -520,8 +532,8 @@ Rcpp::List CPL_read_ogr(Rcpp::CharacterVector datasource, Rcpp::CharacterVector
if (! Rcpp::CharacterVector::is_na(query[0])) {
poLayer = poDS->ExecuteSQL(query[0], NULL, NULL);
if (poLayer == NULL)
Rcpp::stop("SQL execution failed, cannot open layer.\n"); // #nocov
} else
Rcpp::stop("Query execution failed, cannot open layer.\n"); // #nocov
} else
poLayer = poDS->GetLayerByName(layer[0]);
if (poLayer == NULL) {
Rcpp::Rcout << "Cannot open layer " << layer[0] << std::endl;
......@@ -532,7 +544,7 @@ Rcpp::List CPL_read_ogr(Rcpp::CharacterVector datasource, Rcpp::CharacterVector
Rcpp::Rcout << "Reading layer `" << layer[0] << "' from data source `" << datasource[0] << // #nocov
"' using driver `" << poDS->GetDriverName() << "'" << std::endl; // #nocov
Rcpp::List out = sf_from_ogrlayer(poLayer, quiet, int64_as_string, toTypeUser, fid_column_name,
Rcpp::List out = sf_from_ogrlayer(poLayer, quiet, int64_as_string, toTypeUser, fid_column_name,
promote_to_multi);
// clean up if SQL was used https://www.gdal.org/classGDALDataset.html#ab2c2b105b8f76a279e6a53b9b4a182e0
......
......@@ -479,6 +479,7 @@ LINESTRING (0.1707107 0.1707107, 0.8292893 0.82...
> nc = read_sf(system.file("gpkg/nc.gpkg", package="sf"))
> plot(st_geometry(nc))
> ls = try(st_nearest_points(nc[1,], nc))
although coordinates are longitude/latitude, st_nearest_points assumes that they are planar
> # plot(ls, col = 'red', add = TRUE)
> pts = st_cast(ls, "POINT") # gives all start & end points
> # starting, "from" points, corresponding to x: