Nothing
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#' Get GDAL version
#'
#' `gdal_version()` returns runtime version information.
#'
#' @returns Character vector of length four containing:
#' * "–version" - one line version message, e.g., “GDAL 3.6.3, released
#' 2023/03/12”
#' * "GDAL_VERSION_NUM" - formatted as a string, e.g., “3060300” for
#' GDAL 3.6.3.0
#' * "GDAL_RELEASE_DATE" - formatted as a string, e.g., “20230312”
#' * "GDAL_RELEASE_NAME" - e.g., “3.6.3”
#' @examples
#' gdal_version()
gdal_version <- function() {
.Call(`_gdalraster_gdal_version`)
}
#' @noRd
.gdal_version_num <- function() {
.Call(`_gdalraster_gdal_version_num`)
}
#' Retrieve information on GDAL format drivers for raster and vector
#'
#' `gdal_formats()` returns a table of the supported raster and vector
#' formats, with information about the capabilities of each format driver.
#'
#' @param format A character string containing a driver short name. By default,
#' information for all configured raster and vector format drivers will be
#' returned.
#' @returns A data frame containing the format short name, long name, raster
#' (logical), vector (logical), read/write flag (`ro` is read-only,
#' `w` supports CreateCopy, `w+` supports Create), virtual I/O supported
#' (logical), and subdatasets (logical).
#'
#' @note
#' Virtual I/O refers to operations on GDAL Virtual File Systems. See
#' \url{https://gdal.org/en/stable/user/virtual_file_systems.html#virtual-file-systems}.
#'
#' @examples
#' nrow(gdal_formats())
#' head(gdal_formats())
#'
#' gdal_formats("GPKG")
gdal_formats <- function(format = "") {
.Call(`_gdalraster_gdal_formats`, format)
}
#' Get GDAL configuration option
#'
#' `get_config_option()` gets the value of GDAL runtime configuration option.
#' Configuration options are essentially global variables the user can set.
#' They are used to alter the default behavior of certain raster format
#' drivers, and in some cases the GDAL core. For a full description and
#' listing of available options see
#' \url{https://gdal.org/en/stable/user/configoptions.html}.
#'
#' @param key Character name of a configuration option.
#' @returns Character. The value of a (key, value) option previously set with
#' `set_config_option()`. An empty string (`""`) is returned if `key` is not
#' found.
#'
#' @seealso
#' [set_config_option()]
#'
#' `vignette("gdal-config-quick-ref")`
#'
#' @examples
#' ## this option is set during initialization of the gdalraster package
#' get_config_option("OGR_CT_FORCE_TRADITIONAL_GIS_ORDER")
get_config_option <- function(key) {
.Call(`_gdalraster_get_config_option`, key)
}
#' Set GDAL configuration option
#'
#' `set_config_option()` sets a GDAL runtime configuration option.
#' Configuration options are essentially global variables the user can set.
#' They are used to alter the default behavior of certain raster format
#' drivers, and in some cases the GDAL core. For a full description and
#' listing of available options see
#' \url{https://gdal.org/en/stable/user/configoptions.html}.
#'
#' @param key Character name of a configuration option.
#' @param value Character value to set for the option.
#' `value = ""` (empty string) will unset a value previously set by
#' `set_config_option()`.
#' @returns No return value, called for side effects.
#'
#' @seealso
#' [get_config_option()]
#'
#' `vignette("gdal-config-quick-ref")`
#'
#' @examples
#' set_config_option("GDAL_CACHEMAX", "10%")
#' get_config_option("GDAL_CACHEMAX")
#' ## unset:
#' set_config_option("GDAL_CACHEMAX", "")
set_config_option <- function(key, value) {
invisible(.Call(`_gdalraster_set_config_option`, key, value))
}
#' Get the size of memory in use by the GDAL block cache
#'
#' `get_cache_used()` returns the amount of memory currently in use for
#' GDAL block caching. This a wrapper for `GDALGetCacheUsed64()` with return
#' value as MB.
#'
#' @returns Integer. Amount of cache memory in use in MB.
#'
#' @seealso
#' [GDAL Block Cache](https://usdaforestservice.github.io/gdalraster/articles/gdal-block-cache.html)
#'
#' @examples
#' get_cache_used()
get_cache_used <- function() {
.Call(`_gdalraster_get_cache_used`)
}
#' @noRd
.dump_open_datasets <- function(outfile) {
.Call(`_gdalraster_dump_open_datasets`, outfile)
}
#' Push a new GDAL CPLError handler
#'
#' `push_error_handler()` is a wrapper for
#' `CPLPushErrorHandler()` in the GDAL Common Portability
#' Library.
#' This pushes a new error handler on the thread-local error handler stack.
#' This handler will be used until removed with `pop_error_handler()`.
#' A typical use is to temporarily set `CPLQuietErrorHandler()` which doesn't
#' make any attempt to report passed error or warning messages, but will
#' process debug messages via `CPLDefaultErrorHandler`.
#'
#' @param handler Character name of the error handler to push.
#' One of `quiet`, `logging` or `default`.
#' @returns No return value, called for side effects.
#'
#' @note
#' Setting `handler = "logging"` will use `CPLLoggingErrorHandler()`, error
#' handler that logs into the file defined by the `CPL_LOG` configuration
#' option, or `stderr` otherwise.
#'
#' This only affects error reporting from GDAL.
#'
#' @seealso
#' [pop_error_handler()]
#'
#' @examples
#' push_error_handler("quiet")
#' # ...
#' pop_error_handler()
push_error_handler <- function(handler) {
invisible(.Call(`_gdalraster_push_error_handler`, handler))
}
#' Pop error handler off stack
#'
#' `pop_error_handler()` is a wrapper for `CPLPopErrorHandler()` in the GDAL
#' Common Portability Library.
#' Discards the current error handler on the error handler stack, and restores
#' the one in use before the last `push_error_handler()` call. This method has
#' no effect if there are no error handlers on the current thread's error
#' handler stack.
#'
#' @returns No return value, called for side effects.
#'
#' @seealso
#' [push_error_handler()]
#'
#' @examples
#' push_error_handler("quiet")
#' # ...
#' pop_error_handler()
pop_error_handler <- function() {
invisible(.Call(`_gdalraster_pop_error_handler`))
}
#' Check a filename before passing to GDAL and potentially fix.
#' 'filename' may be a physical file, URL, connection string, filename with
#' additional parameters, etc.
#' Currently, only checks for leading tilde and does path expasion in that
#' case. Returns the filename in UTF-8 encoding if possible using R enc2utf8.
#'
#' @noRd
.check_gdal_filename <- function(filename) {
.Call(`_gdalraster_check_gdal_filename`, filename)
}
#' Get the number of processors detected by GDAL
#'
#' `get_num_cpus()` returns the number of processors detected by GDAL.
#' Wrapper of `CPLGetNumCPUs()` in the GDAL Common Portability Library.
#'
#' @return Integer scalar, number of CPUs.
#'
#' @examples
#' get_num_cpus()
get_num_cpus <- function() {
.Call(`_gdalraster_get_num_cpus`)
}
#' Get usable physical RAM reported by GDAL
#'
#' `get_usable_physical_ram()` returns the total physical RAM, usable by a
#' process, in bytes. It will limit to 2 GB for 32 bit processes. Starting
#' with GDAL 2.4.0, it will also take into account resource limits (virtual
#' memory) on Posix systems. Starting with GDAL 3.6.1, it will also take into
#' account RLIMIT_RSS on Linux. Wrapper of `CPLGetUsablePhysicalRAM()` in the
#' GDAL Common Portability Library.
#'
#' @return Numeric scalar, number of bytes as `bit64::integer64` type (or 0 in
#' case of failure).
#'
#' @note
#' This memory may already be partly used by other processes.
#'
#' @examples
#' get_usable_physical_ram()
get_usable_physical_ram <- function() {
.Call(`_gdalraster_get_usable_physical_ram`)
}
#' Is SpatiaLite available?
#'
#' `has_spatialite()` returns a logical value indicating whether GDAL was
#' built with support for the SpatiaLite library. SpatiaLite extends the
#' SQLite core to support full Spatial SQL capabilities.
#'
#' @details
#' GDAL supports executing SQL statements against a datasource. For most file
#' formats (e.g. Shapefiles, GeoJSON, FlatGeobuf files), the built-in OGR SQL
#' dialect will be used by default. It is also possible to request the
#' alternate `"SQLite"` dialect, which will use the SQLite engine to evaluate
#' commands on GDAL datasets. This assumes that GDAL is built with support for
#' SQLite, and preferably with Spatialite support too to benefit from spatial
#' functions.
#'
#' @return Logical scalar. `TRUE` if SpatiaLite is available to GDAL.
#'
#' @note
#' All GDAL/OGR drivers for database systems, e.g., PostgreSQL / PostGIS,
#' Oracle Spatial, SQLite / Spatialite RDBMS, GeoPackage, etc., override the
#' `GDALDataset::ExecuteSQL()` function with a dedicated implementation and, by
#' default, pass the SQL statements directly to the underlying RDBMS. In these
#' cases the SQL syntax varies in some particulars from OGR SQL. Also, anything
#' possible in SQL can then be accomplished for these particular databases. For
#' those drivers, it is also possible to explicitly request the `OGRSQL` or
#' `SQLite` dialects, although performance will generally be much less than the
#' native SQL engine of those database systems.
#'
#' @seealso
#' [ogrinfo()], [ogr_execute_sql()]
#'
#' OGR SQL dialect and SQLITE SQL dialect:\cr
#' \url{https://gdal.org/en/stable/user/ogr_sql_sqlite_dialect.html}
#'
#' @examples
#' has_spatialite()
has_spatialite <- function() {
.Call(`_gdalraster_has_spatialite`)
}
#' Check if GDAL CPLHTTP services can be useful (libcurl)
#'
#' `http_enabled()` returns `TRUE` if `libcurl` support is enabled.
#' Wrapper of `CPLHTTPEnabled()` in the GDAL Common Portability Library.
#'
#' @return Logical scalar, `TRUE` if GDAL was built with `libcurl` support.
#'
#' @examples
#' http_enabled()
http_enabled <- function() {
.Call(`_gdalraster_http_enabled`)
}
#' @noRd
.cpl_http_cleanup <- function() {
invisible(.Call(`_gdalraster_cpl_http_cleanup`))
}
#' Create a new uninitialized raster
#'
#' `create()` makes an empty raster in the specified format.
#'
#' @param format Raster format short name (e.g., "GTiff").
#' @param dst_filename Filename to create.
#' @param xsize Integer width of raster in pixels.
#' @param ysize Integer height of raster in pixels.
#' @param nbands Integer number of bands.
#' @param dataType Character data type name.
#' (e.g., common data types include Byte, Int16, UInt16, Int32, Float32).
#' @param options Optional list of format-specific creation options in a
#' vector of `"NAME=VALUE"` pairs
#' (e.g., \code{options = c("COMPRESS=LZW")} to set LZW
#' compression during creation of a GTiff file).
#' The APPEND_SUBDATASET=YES option can be
#' specified to avoid prior destruction of existing dataset.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#' @seealso
#' [`GDALRaster-class`][GDALRaster], [createCopy()], [rasterFromRaster()],
#' [getCreationOptions()]
#' @examples
#' new_file <- file.path(tempdir(), "newdata.tif")
#' create(format="GTiff", dst_filename=new_file, xsize=143, ysize=107,
#' nbands=1, dataType="Int16")
#' ds <- new(GDALRaster, new_file, read_only=FALSE)
#' ## EPSG:26912 - NAD83 / UTM zone 12N
#' ds$setProjection(epsg_to_wkt(26912))
#' gt <- c(323476.1, 30, 0, 5105082.0, 0, -30)
#' ds$setGeoTransform(gt)
#' ds$setNoDataValue(band = 1, -9999)
#' ds$fillRaster(band = 1, -9999, 0)
#' ## ...
#' ## close the dataset when done
#' ds$close()
#'
#' deleteDataset(new_file)
create <- function(format, dst_filename, xsize, ysize, nbands, dataType, options = NULL) {
invisible(.Call(`_gdalraster_create`, format, dst_filename, xsize, ysize, nbands, dataType, options))
}
#' Create a copy of a raster
#'
#' `createCopy()` copies a raster dataset, optionally changing the format.
#' The extent, cell size, number of bands, data type, projection, and
#' geotransform are all copied from the source raster.
#'
#' @param format Format short name for the output raster
#' (e.g., "GTiff" or "HFA").
#' @param dst_filename Filename to create.
#' @param src_filename Filename of source raster.
#' @param strict Logical. TRUE if the copy must be strictly equivalent,
#' or more normally FALSE indicating that the copy may adapt as needed for
#' the output format.
#' @param options Optional list of format-specific creation options in a
#' vector of `"NAME=VALUE"` pairs
#' (e.g., \code{options = c("COMPRESS=LZW")} to set \code{LZW}
#' compression during creation of a GTiff file).
#' The APPEND_SUBDATASET=YES option can be
#' specified to avoid prior destruction of existing dataset.
#' @param quiet Logical scalar. If `TRUE`, a progress bar will be not be
#' displayed. Defaults to `FALSE`.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#' @seealso
#' [`GDALRaster-class`][GDALRaster], [create()], [rasterFromRaster()],
#' [getCreationOptions()], [translate()]
#' @examples
#' lcp_file <- system.file("extdata/storm_lake.lcp", package="gdalraster")
#' tif_file <- file.path(tempdir(), "storml_lndscp.tif")
#' opt <- c("COMPRESS=LZW")
#' createCopy(format="GTiff", dst_filename=tif_file, src_filename=lcp_file,
#' options=opt)
#' file.size(lcp_file)
#' file.size(tif_file)
#' ds <- new(GDALRaster, tif_file, read_only=FALSE)
#' ds$getMetadata(band=0, domain="IMAGE_STRUCTURE")
#' for (band in 1:ds$getRasterCount())
#' ds$setNoDataValue(band, -9999)
#' ds$getStatistics(band=1, approx_ok=FALSE, force=TRUE)
#' ds$close()
#'
#' deleteDataset(tif_file)
createCopy <- function(format, dst_filename, src_filename, strict = FALSE, options = NULL, quiet = FALSE) {
invisible(.Call(`_gdalraster_createCopy`, format, dst_filename, src_filename, strict, options, quiet))
}
#' Apply geotransform - internal wrapper of GDALApplyGeoTransform()
#'
#' `apply_geotransform_()` applies geotransform coefficients to a raster
#' coordinate in pixel/line space (colum/row), converting into a
#' georeferenced (x, y) coordinate.
#'
#' @param gt Numeric vector of length six containing the geotransform to
#' apply.
#' @param pixel Numeric scalar. A raster pixel (column) coordinate.
#' @param line Numeric scalar. A raster line (row) coordinate.
#' @returns Numeric vector of length two containing a geospatial x/y
#' coordinate (spatial reference system of `gt`).
#' @seealso [`GDALRaster$getGeoTransform()`][GDALRaster], [get_pixel_line()],
#' [inv_geotransform()]
#' @noRd
.apply_geotransform <- function(gt, pixel, line) {
.Call(`_gdalraster_apply_geotransform_`, gt, pixel, line)
}
#' Apply geotransform (raster column/row to geospatial x/y)
#' input as geotransform vector, no bounds checking on col/row
#' @noRd
.apply_geotransform_gt <- function(col_row, gt) {
.Call(`_gdalraster_apply_geotransform_gt`, col_row, gt)
}
#' Apply geotransform (raster column/row to geospatial x/y)
#' alternate version for GDALRaster input, with bounds checking
#' @noRd
.apply_geotransform_ds <- function(col_row, ds) {
.Call(`_gdalraster_apply_geotransform_ds`, col_row, ds)
}
#' Invert geotransform
#'
#' `inv_geotransform()` inverts a vector of geotransform coefficients. This
#' converts the equation from being:\cr
#' raster pixel/line (column/row) -> geospatial x/y coordinate\cr
#' to:\cr
#' geospatial x/y coordinate -> raster pixel/line (column/row)
#'
#' @param gt Numeric vector of length six containing the geotransform to
#' invert.
#' @returns Numeric vector of length six containing the inverted
#' geotransform. The output vector will contain NAs if the input geotransform
#' is uninvertable.
#' @seealso [`GDALRaster$getGeoTransform()`][GDALRaster], [get_pixel_line()]
#' @examples
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' ds <- new(GDALRaster, elev_file)
#' invgt <- ds$getGeoTransform() |> inv_geotransform()
#' ds$close()
#'
#' ptX = 324181.7
#' ptY = 5103901.4
#'
#' ## for a point x, y in the spatial reference system of elev_file
#' ## raster pixel (column number):
#' pixel <- floor(invgt[1] +
#' invgt[2] * ptX +
#' invgt[3] * ptY)
#'
#' ## raster line (row number):
#' line <- floor(invgt[4] +
#' invgt[5] * ptX +
#' invgt[6] * ptY)
#'
#' ## get_pixel_line() applies this conversion
inv_geotransform <- function(gt) {
.Call(`_gdalraster_inv_geotransform`, gt)
}
#' Raster pixel/line from geospatial x,y coordinates
#' input is gt vector, no bounds checking done on output
#' @noRd
.get_pixel_line_gt <- function(xy, gt) {
.Call(`_gdalraster_get_pixel_line_gt`, xy, gt)
}
#' Raster pixel/line from geospatial x,y coordinates
#' alternate version for GDALRaster input, with bounds checking
#' @noRd
.get_pixel_line_ds <- function(xy, ds) {
.Call(`_gdalraster_get_pixel_line_ds`, xy, ds)
}
#' Build a GDAL virtual raster from a list of datasets
#'
#' `buildVRT()` is a wrapper of the \command{gdalbuildvrt} command-line
#' utility for building a VRT (Virtual Dataset) that is a mosaic of the list
#' of input GDAL datasets
#' (see \url{https://gdal.org/en/stable/programs/gdalbuildvrt.html}).
#'
#' @details
#' Several command-line options are described in the GDAL documentation at the
#' URL above. By default, the input files are considered as tiles of a larger
#' mosaic and the VRT file has as many bands as one of the input files.
#' Alternatively, the `-separate` argument can be used to put each input
#' raster into a separate band in the VRT dataset.
#'
#' Some amount of checks are done to assure that all files that will be put in
#' the resulting VRT have similar characteristics: number of bands,
#' projection, color interpretation.... If not, files that do not match the
#' common characteristics will be skipped. (This is true in the default
#' mode for virtual mosaicing, and not when using the `-separate` option).
#'
#' In a virtual mosaic, if there is spatial overlap between
#' input rasters then the order of files appearing in the list of
#' sources matter: files that are listed at the end are the ones
#' from which the data will be fetched. Note that nodata will be taken into
#' account to potentially fetch data from less priority datasets.
#'
#' @param vrt_filename Character string. Filename of the output VRT.
#' @param input_rasters Character vector of input raster filenames.
#' @param cl_arg Optional character vector of command-line arguments to
#' \code{gdalbuildvrt}.
#' @param quiet Logical scalar. If `TRUE`, a progress bar will not be
#' displayed. Defaults to `FALSE`.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#'
#' @seealso
#' [rasterToVRT()]
#'
#' @examples
#' # build a virtual 3-band RGB raster from individual Landsat band files
#' b4_file <- system.file("extdata/sr_b4_20200829.tif", package="gdalraster")
#' b5_file <- system.file("extdata/sr_b5_20200829.tif", package="gdalraster")
#' b6_file <- system.file("extdata/sr_b6_20200829.tif", package="gdalraster")
#' band_files <- c(b6_file, b5_file, b4_file)
#' vrt_file <- file.path(tempdir(), "storml_b6_b5_b4.vrt")
#' buildVRT(vrt_file, band_files, cl_arg = "-separate")
#' ds <- new(GDALRaster, vrt_file)
#' ds$getRasterCount()
#' plot_raster(ds, nbands=3, main="Landsat 6-5-4 (vegetative analysis)")
#' ds$close()
#'
#' vsi_unlink(vrt_file)
buildVRT <- function(vrt_filename, input_rasters, cl_arg = NULL, quiet = FALSE) {
invisible(.Call(`_gdalraster_buildVRT`, vrt_filename, input_rasters, cl_arg, quiet))
}
#' Raster overlay for unique combinations
#'
#' @description
#' `combine()` overlays multiple rasters so that a unique ID is assigned to
#' each unique combination of input values. The input raster layers
#' typically have integer data types (floating point will be coerced to
#' integer by truncation), and must have the same projection, extent and cell
#' size. Pixel counts for each unique combination are obtained, and
#' combination IDs are optionally written to an output raster.
#'
#' Called from and documented in R/gdalraster_proc.R
#' @noRd
.combine <- function(src_files, var_names, bands, dst_filename = "", fmt = "", dataType = "UInt32", options = NULL, quiet = FALSE) {
.Call(`_gdalraster_combine`, src_files, var_names, bands, dst_filename, fmt, dataType, options, quiet)
}
#' Compute for a raster band the set of unique pixel values and their counts
#'
#' @noRd
.value_count <- function(src_ds, band = 1L, quiet = FALSE) {
.Call(`_gdalraster_value_count`, src_ds, band, quiet)
}
#' Wrapper for GDALDEMProcessing in the GDAL Algorithms C API
#'
#' Called from and documented in R/gdalraster_proc.R
#' @noRd
.dem_proc <- function(mode, src_filename, dst_filename, cl_arg = NULL, col_file = NULL, quiet = FALSE) {
.Call(`_gdalraster_dem_proc`, mode, src_filename, dst_filename, cl_arg, col_file, quiet)
}
#' Fill selected pixels by interpolation from surrounding areas
#'
#' `fillNodata()` is a wrapper for `GDALFillNodata()` in the GDAL Algorithms
#' API. This algorithm will interpolate values for all designated nodata
#' pixels (pixels having an intrinsic nodata value, or marked by zero-valued
#' pixels in the optional raster specified in `mask_file`). For each nodata
#' pixel, a four direction conic search is done to find values to interpolate
#' from (using inverse distance weighting).
#' Once all values are interpolated, zero or more smoothing iterations
#' (3x3 average filters on interpolated pixels) are applied to smooth out
#' artifacts.
#'
#' @note
#' The input raster will be modified in place. It should not be open in a
#' `GDALRaster` object while processing with `fillNodata()`.
#'
#' @param filename Filename of input raster in which to fill nodata pixels.
#' @param band Integer band number to modify in place.
#' @param mask_file Optional filename of raster to use as a validity mask
#' (band 1 is used, zero marks nodata pixels, non-zero marks valid pixels).
#' @param max_dist Maximum distance (in pixels) that the algorithm
#' will search out for values to interpolate (100 pixels by default).
#' @param smooth_iterations The number of 3x3 average filter smoothing
#' iterations to run after the interpolation to dampen artifacts
#' (0 by default).
#' @param quiet Logical scalar. If `TRUE`, a progress bar will not be
#' displayed. Defaults to `FALSE`.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#' @examples
#' ## fill nodata edge pixels in the elevation raster
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#'
#' ## get count of nodata
#' tbl <- buildRAT(elev_file)
#' head(tbl)
#' tbl[is.na(tbl$VALUE),]
#'
#' ## make a copy that will be modified
#' mod_file <- file.path(tempdir(), "storml_elev_fill.tif")
#' file.copy(elev_file, mod_file)
#'
#' fillNodata(mod_file, band=1)
#'
#' mod_tbl = buildRAT(mod_file)
#' head(mod_tbl)
#' mod_tbl[is.na(mod_tbl$VALUE),]
#'
#' deleteDataset(mod_file)
fillNodata <- function(filename, band, mask_file = "", max_dist = 100, smooth_iterations = 0L, quiet = FALSE) {
invisible(.Call(`_gdalraster_fillNodata`, filename, band, mask_file, max_dist, smooth_iterations, quiet))
}
#' Compute footprint of a raster
#'
#' `footprint()` is a wrapper of the \command{gdal_footprint} command-line
#' utility (see \url{https://gdal.org/en/stable/programs/gdal_footprint.html}).
#' The function can be used to compute the footprint of a raster file, taking
#' into account nodata values (or more generally the mask band attached to
#' the raster bands), and generating polygons/multipolygons corresponding to
#' areas where pixels are valid, and write to an output vector file.
#' Refer to the GDAL documentation at the URL above for a list of command-line
#' arguments that can be passed in `cl_arg`. Requires GDAL >= 3.8.
#'
#' @details
#' Post-vectorization geometric operations are applied in the following order:
#' * optional splitting (`-split_polys`)
#' * optional densification (`-densify`)
#' * optional reprojection (`-t_srs`)
#' * optional filtering by minimum ring area (`-min_ring_area`)
#' * optional application of convex hull (`-convex_hull`)
#' * optional simplification (`-simplify`)
#' * limitation of number of points (`-max_points`)
#'
#' @param src_filename Character string. Filename of the source raster.
#' @param dst_filename Character string. Filename of the destination vector.
#' If the file and the output layer exist, the new footprint is appended to
#' them, unless the `-overwrite` command-line argument is used.
#' @param cl_arg Optional character vector of command-line arguments for
#' \code{gdal_footprint}.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#'
#' @seealso
#' [polygonize()]
#'
#' @examples
#' evt_file <- system.file("extdata/storml_evt.tif", package="gdalraster")
#' out_file <- file.path(tempdir(), "storml.geojson")
#'
#' # Requires GDAL >= 3.8
#' if (as.integer(gdal_version()[2]) >= 3080000) {
#' # command-line arguments for gdal_footprint
#' args <- c("-t_srs", "EPSG:4326")
#' footprint(evt_file, out_file, args)
#'
#' deleteDataset(out_file)
#' }
footprint <- function(src_filename, dst_filename, cl_arg = NULL) {
invisible(.Call(`_gdalraster_footprint`, src_filename, dst_filename, cl_arg))
}
#' Convert vector data between different formats
#'
#' `ogr2ogr()` is a wrapper of the \command{ogr2ogr} command-line
#' utility (see \url{https://gdal.org/en/stable/programs/ogr2ogr.html}).
#' This function can be used to convert simple features data between file
#' formats. It can also perform various operations during the process, such
#' as spatial or attribute selection, reducing the set of attributes, setting
#' the output coordinate system or even reprojecting the features during
#' translation.
#' Refer to the GDAL documentation at the URL above for a description of
#' command-line arguments that can be passed in `cl_arg`.
#'
#' @param src_dsn Character string. Data source name of the source vector
#' dataset.
#' @param dst_dsn Character string. Data source name of the destination vector
#' dataset.
#' @param src_layers Optional character vector of layer names in the source
#' dataset. Defaults to all layers.
#' @param cl_arg Optional character vector of command-line arguments for
#' the GDAL \code{ogr2ogr} command-line utility (see URL above).
#' @param open_options Optional character vector of dataset open options.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#'
#' @note
#' For progress reporting, see command-line argument `-progress`: Display
#' progress on terminal. Only works if input layers have the "fast feature
#' count" capability.
#'
#' @seealso
#' [ogrinfo()], the [ogr_manage] utilities
#'
#' [translate()] for raster data
#'
#' @examples
#' src <- system.file("extdata/ynp_fires_1984_2022.gpkg", package="gdalraster")
#'
#' # Convert GeoPackage to Shapefile
#' shp_file <- file.path(tempdir(), "ynp_fires.shp")
#' ogr2ogr(src, shp_file, src_layers = "mtbs_perims")
#'
#' # Reproject to WGS84
#' ynp_wgs84 <- file.path(tempdir(), "ynp_fires_wgs84.gpkg")
#' args <- c("-t_srs", "EPSG:4326")
#' ogr2ogr(src, ynp_wgs84, cl_arg = args)
#'
#' # Clip to a bounding box (xmin, ymin, xmax, ymax in the source SRS)
#' # This will select features whose geometry intersects the bounding box.
#' # The geometries themselves will not be clipped unless "-clipsrc" is
#' # specified.
#' # The source SRS can be overridden with "-spat_srs" "<srs_def>"
#' ynp_clip <- file.path(tempdir(), "ynp_fires_aoi_clip.gpkg")
#' bb <- c(469685.97, 11442.45, 544069.63, 85508.15)
#' args <- c("-spat", bb)
#' ogr2ogr(src, ynp_clip, cl_arg = args)
#'
#' # Filter features by a -where clause
#' ynp_filtered <- file.path(tempdir(), "ynp_fires_2000_2022.gpkg")
#' sql <- "ig_year >= 2000 ORDER BY ig_year"
#' args <- c("-where", sql)
#' ogr2ogr(src, ynp_filtered, src_layers = "mtbs_perims", cl_arg = args)
#'
#' deleteDataset(shp_file)
#' deleteDataset(ynp_wgs84)
#' deleteDataset(ynp_clip)
#' deleteDataset(ynp_filtered)
ogr2ogr <- function(src_dsn, dst_dsn, src_layers = NULL, cl_arg = NULL, open_options = NULL) {
invisible(.Call(`_gdalraster_ogr2ogr`, src_dsn, dst_dsn, src_layers, cl_arg, open_options))
}
#' Retrieve information about a vector data source
#'
#' `ogrinfo()` is a wrapper of the \command{ogrinfo} command-line
#' utility (see \url{https://gdal.org/en/stable/programs/ogrinfo.html}).
#' This function lists information about an OGR-supported data source.
#' It is also possible to edit data with SQL statements.
#' Refer to the GDAL documentation at the URL above for a description of
#' command-line arguments that can be passed in `cl_arg`.
#' Requires GDAL >= 3.7.
#'
#' @param dsn Character string. Data source name (e.g., filename, database
#' connection string, etc.)
#' @param layers Optional character vector of layer names in the source
#' dataset.
#' @param cl_arg Optional character vector of command-line arguments for
#' the \code{ogrinfo} command-line utility in GDAL (see URL above for
#' reference). The default is `c("-so", "-nomd")` (see Note).
#' @param open_options Optional character vector of dataset open options.
#' @param read_only Logical scalar. `TRUE` to open the data source read-only
#' (the default), or `FALSE` to open with write access.
#' @param cout Logical scalar. `TRUE` to write info to the standard C output
#' stream (the default). `FALSE` to suppress console output.
#' @returns Invisibly, a character string containing information about the
#' vector dataset, or empty string (`""`) in case of error.
#'
#' @note
#' The command-line argument `-so` provides a summary only, i.e., does not
#' include details about every single feature of a layer.
#' `-nomd` suppresses metadata printing. Some datasets may contain a lot of
#' metadata strings.
#'
#' @seealso
#' [ogr2ogr()], the [ogr_manage] utilities
#'
#' @examples
#' src <- system.file("extdata/ynp_fires_1984_2022.gpkg", package="gdalraster")
#'
#' # Requires GDAL >= 3.7
#' if (as.integer(gdal_version()[2]) >= 3070000) {
#' # Get the names of the layers in a GeoPackage file.
#' ogrinfo(src)
#'
#' # Summary of a layer
#' ogrinfo(src, "mtbs_perims")
#'
#' # JSON format
#' args <- c("-json", "-nomd")
#' json <- ogrinfo(src, "mtbs_perims", args, cout = FALSE)
#' #info <- jsonlite::fromJSON(json)
#'
#' # Query an attribute to restrict the output of the features in a layer
#' args <- c("-ro", "-nomd", "-where", "ig_year = 2020")
#' ogrinfo(src, "mtbs_perims", args)
#'
#' # Copy to a temporary in-memory file that is writeable
#' src_mem <- paste0("/vsimem/", basename(src))
#' vsi_copy_file(src, src_mem)
#' print(src_mem)
#'
#' # Add a column to a layer
#' args <- c("-sql", "ALTER TABLE mtbs_perims ADD burn_bnd_ha float")
#' ogrinfo(src_mem, cl_arg = args, read_only = FALSE)
#'
#' # Update values of the column with SQL and specify a dialect
#' sql <- "UPDATE mtbs_perims SET burn_bnd_ha = (burn_bnd_ac / 2.471)"
#' args <- c("-dialect", "sqlite", "-sql", sql)
#' ogrinfo(src_mem, cl_arg = args, read_only = FALSE)
#'
#' vsi_unlink(src_mem)
#' }
ogrinfo <- function(dsn, layers = NULL, cl_arg = as.character( c("-so", "-nomd")), open_options = NULL, read_only = TRUE, cout = TRUE) {
invisible(.Call(`_gdalraster_ogrinfo`, dsn, layers, cl_arg, open_options, read_only, cout))
}
#' Wrapper for GDALPolygonize in the GDAL Algorithms C API
#'
#' Called from and documented in R/gdalraster_proc.R
#' @noRd
.polygonize <- function(src_filename, src_band, out_dsn, out_layer, fld_name, mask_file = "", nomask = FALSE, connectedness = 4L, quiet = FALSE) {
.Call(`_gdalraster_polygonize`, src_filename, src_band, out_dsn, out_layer, fld_name, mask_file, nomask, connectedness, quiet)
}
#' Wrapper for GDALRasterize in the GDAL Algorithms C API
#'
#' Called from and documented in R/gdalraster_proc.R
#' @noRd
.rasterize <- function(src_dsn, dst_filename, cl_arg, quiet = FALSE) {
.Call(`_gdalraster_rasterize`, src_dsn, dst_filename, cl_arg, quiet)
}
#' Remove small raster polygons
#'
#' `sieveFilter()` is a wrapper for `GDALSieveFilter()` in the GDAL Algorithms
#' API. It removes raster polygons smaller than a provided threshold size
#' (in pixels) and replaces them with the pixel value of the largest neighbour
#' polygon.
#'
#' @details
#' Polygons are determined as regions of the raster where the pixels all have
#' the same value, and that are contiguous (connected).
#' Pixels determined to be "nodata" per the mask band will not be
#' treated as part of a polygon regardless of their pixel values. Nodata areas
#' will never be changed nor affect polygon sizes. Polygons smaller than the
#' threshold with no neighbours that are as large as the threshold will not be
#' altered. Polygons surrounded by nodata areas will therefore not be altered.
#'
#' The algorithm makes three passes over the input file to enumerate the
#' polygons and collect limited information about them. Memory use is
#' proportional to the number of polygons (roughly 24 bytes per polygon), but
#' is not directly related to the size of the raster. So very large raster
#' files can be processed effectively if there aren't too many polygons. But
#' extremely noisy rasters with many one pixel polygons will end up being
#' expensive (in memory) to process.
#'
#' The input dataset is read as integer data which means that floating point
#' values are rounded to integers.
#'
#' @param src_filename Filename of the source raster to be processed.
#' @param src_band Band number in the source raster to be processed.
#' @param dst_filename Filename of the output raster. It may be the same as
#' `src_filename` to update the source file in place.
#' @param dst_band Band number in `dst_filename` to write output. It may be
#' the same as `src_band` to update the source raster in place.
#' @param size_threshold Integer. Raster polygons with sizes (in pixels)
#' smaller than this value will be merged into their largest neighbour.
#' @param connectedness Integer. Either `4` indicating that diagonal pixels
#' are not considered directly adjacent for polygon membership purposes, or
#' `8` indicating they are.
#' @param mask_filename Optional filename of raster to use as a mask.
#' @param mask_band Band number in `mask_filename` to use as a mask. All
#' pixels in the mask band with a value other than zero will be considered
#' suitable for inclusion in polygons.
#' @param options Algorithm options as a character vector of name=value pairs.
#' None currently supported.
#' @param quiet Logical scalar. If `TRUE`, a progress bar will not be
#' displayed. Defaults to `FALSE`.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#'
#' @examples
#' ## remove single-pixel polygons from the vegetation type layer (EVT)
#' evt_file <- system.file("extdata/storml_evt.tif", package="gdalraster")
#'
#' # create a blank raster to hold the output
#' evt_mmu_file <- file.path(tempdir(), "storml_evt_mmu2.tif")
#' rasterFromRaster(srcfile = evt_file,
#' dstfile = evt_mmu_file,
#' init = 32767)
#'
#' # create a mask to exclude water pixels from the algorithm
#' # recode water (7292) to 0
#' expr <- "ifelse(EVT == 7292, 0, EVT)"
#' mask_file <- calc(expr = expr,
#' rasterfiles = evt_file,
#' var.names = "EVT")
#'
#' # create a version of EVT with two-pixel minimum mapping unit
#' sieveFilter(src_filename = evt_file,
#' src_band = 1,
#' dst_filename = evt_mmu_file,
#' dst_band = 1,
#' size_threshold = 2,
#' connectedness = 8,
#' mask_filename = mask_file,
#' mask_band = 1)
#'
#' deleteDataset(mask_file)
#' deleteDataset(evt_mmu_file)
sieveFilter <- function(src_filename, src_band, dst_filename, dst_band, size_threshold, connectedness, mask_filename = "", mask_band = 0L, options = NULL, quiet = FALSE) {
invisible(.Call(`_gdalraster_sieveFilter`, src_filename, src_band, dst_filename, dst_band, size_threshold, connectedness, mask_filename, mask_band, options, quiet))
}
#' Convert raster data between different formats
#'
#' `translate()` is a wrapper of the \command{gdal_translate} command-line
#' utility (see \url{https://gdal.org/en/stable/programs/gdal_translate.html}).
#' The function can be used to convert raster data between different
#' formats, potentially performing some operations like subsetting,
#' resampling, and rescaling pixels in the process. Refer to the GDAL
#' documentation at the URL above for a list of command-line arguments that
#' can be passed in `cl_arg`.
#'
#' @param src_filename Character string. Filename of the source raster.
#' @param dst_filename Character string. Filename of the output raster.
#' @param cl_arg Optional character vector of command-line arguments for
#' \code{gdal_translate} (see URL above).
#' @param quiet Logical scalar. If `TRUE`, a progress bar will not be
#' displayed. Defaults to `FALSE`.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#'
#' @seealso
#' [`GDALRaster-class`][GDALRaster], [rasterFromRaster()], [warp()]
#'
#' [ogr2ogr()] for vector data
#'
#' @examples
#' # convert the elevation raster to Erdas Imagine format and resample to 90m
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#'
#' # command-line arguments for gdal_translate
#' args <- c("-tr", "90", "90", "-r", "average")
#' args <- c(args, "-of", "HFA", "-co", "COMPRESSED=YES")
#'
#' img_file <- file.path(tempdir(), "storml_elev_90m.img")
#' translate(elev_file, img_file, args)
#'
#' ds <- new(GDALRaster, img_file)
#' ds$getDriverLongName()
#' ds$bbox()
#' ds$res()
#' ds$getStatistics(band=1, approx_ok=FALSE, force=TRUE)
#' ds$close()
#'
#' deleteDataset(img_file)
translate <- function(src_filename, dst_filename, cl_arg = NULL, quiet = FALSE) {
invisible(.Call(`_gdalraster_translate`, src_filename, dst_filename, cl_arg, quiet))
}
#' Raster reprojection and mosaicing
#'
#' `warp()` is a wrapper of the \command{gdalwarp} command-line utility for
#' raster mosaicing, reprojection and warping
#' (see \url{https://gdal.org/en/stable/programs/gdalwarp.html}).
#' The function can reproject to any supported spatial reference system (SRS).
#' It can also be used to crop, resample, and optionally write output to a
#' different raster format. See Details for a list of commonly used
#' processing options that can be passed as arguments to `warp()`.
#'
#' @details
#' Several processing options can be performed in one call to `warp()` by
#' passing the necessary command-line arguments. The following list describes
#' several commonly used arguments. Note that `gdalwarp` supports a large
#' number of arguments that enable a variety of different processing options.
#' Users are encouraged to review the original source documentation provided
#' by the GDAL project at the URL above for the full list.
#'
#' * `-te <xmin> <ymin> <xmax> <ymax>`\cr
#' Georeferenced extents of output file to be created (in target SRS by
#' default).
#' * `-te_srs <srs_def>`\cr
#' SRS in which to interpret the coordinates given with `-te`
#' (if different than `t_srs`).
#' * `-tr <xres> <yres>`\cr
#' Output pixel resolution (in target georeferenced units).
#' * `-tap`\cr
#' (target aligned pixels) align the coordinates of the extent of the output
#' file to the values of the `-tr`, such that the aligned extent includes
#' the minimum extent. Alignment means that xmin / resx, ymin / resy,
#' xmax / resx and ymax / resy are integer values.
#' * `-ovr <level>|AUTO|AUTO-<n>|NONE`\cr
#' Specify which overview level of source files must be used. The default
#' choice, `AUTO`, will select the overview level whose resolution is the
#' closest to the target resolution. Specify an integer value (0-based,
#' i.e., 0=1st overview level) to select a particular level. Specify
#' `AUTO-n` where `n` is an integer greater or equal to `1`, to select an
#' overview level below the `AUTO` one. Or specify `NONE` to force the base
#' resolution to be used (can be useful if overviews have been generated
#' with a low quality resampling method, and the warping is done using a
#' higher quality resampling method).
#' * `-wo <NAME>=<VALUE>`\cr
#' Set a warp option as described in the GDAL documentation for
#' [`GDALWarpOptions`](https://gdal.org/en/stable/api/gdalwarp_cpp.html#_CPPv415GDALWarpOptions)
#' Multiple `-wo` may be given. See also `-multi` below.
#' * `-ot <type>`\cr
#' Force the output raster bands to have a specific data type supported by
#' the format, which may be one of the following: `Byte`, `Int8`, `UInt16`,
#' `Int16`, `UInt32`, `Int32`, `UInt64`, `Int64`, `Float32`, `Float64`,
#' `CInt16`, `CInt32`, `CFloat32` or `CFloat64`.
#' * `-r <resampling_method>`\cr
#' Resampling method to use. Available methods are: `near` (nearest
#' neighbour, the default), `bilinear`, `cubic`, `cubicspline`, `lanczos`,
#' `average`, `rms` (root mean square, GDAL >= 3.3), `mode`, `max`, `min`,
#' `med`, `q1` (first quartile), `q3` (third quartile), `sum` (GDAL >= 3.1).
#' * `-srcnodata "<value>[ <value>]..."`\cr
#' Set nodata masking values for input bands (different values can be
#' supplied for each band). If more than one value is supplied all values
#' should be quoted to keep them together as a single operating system
#' argument. Masked values will not be used in interpolation. Use a value of
#' `None` to ignore intrinsic nodata settings on the source dataset.
#' If `-srcnodata` is not explicitly set, but the source dataset has nodata
#' values, they will be taken into account by default.
#' * `-dstnodata "<value>[ <value>]..."`\cr
#' Set nodata values for output bands (different values can be supplied for
#' each band). If more than one value is supplied all values should be
#' quoted to keep them together as a single operating system argument. New
#' files will be initialized to this value and if possible the nodata value
#' will be recorded in the output file. Use a value of `"None"` to ensure
#' that nodata is not defined. If this argument is not used then nodata
#' values will be copied from the source dataset.
#' * `-wm <memory_in_mb>`\cr
#' Set the amount of memory that the warp API is allowed to use for caching.
#' The value is interpreted as being in megabytes if the value is <10000.
#' For values >=10000, this is interpreted as bytes. The warper will
#' total up the memory required to hold the input and output image arrays
#' and any auxiliary masking arrays and if they are larger than the
#' "warp memory" allowed it will subdivide the chunk into smaller chunks and
#' try again. If the `-wm` value is very small there is some extra overhead
#' in doing many small chunks so setting it larger is better but it is a
#' matter of diminishing returns.
#' * `-multi`\cr
#' Use multithreaded warping implementation. Two threads will be used to
#' process chunks of image and perform input/output operation
#' simultaneously. Note that computation is not multithreaded itself. To do
#' that, you can use the `-wo NUM_THREADS=val/ALL_CPUS` option, which can be
#' combined with `-multi`.
#' * `-of <format>`
#' Set the output raster format. Will be guessed from the extension if not
#' specified. Use the short format name (e.g., `"GTiff"`).
#' * `-co <NAME>=<VALUE>`\cr
#' Set one or more format specific creation options for the output dataset.
#' For example, the GeoTIFF driver supports creation options to control
#' compression, and whether the file should be tiled.
#' [getCreationOptions()] can be used to look up available creation options,
#' but the GDAL [Raster drivers](https://gdal.org/en/stable/drivers/raster/index.html)
#' documentation is the definitive reference for format specific options.
#' Multiple `-co` may be given, e.g.,
#' \preformatted{ c("-co", "COMPRESS=LZW", "-co", "BIGTIFF=YES") }
#' * `-overwrite`\cr
#' Overwrite the target dataset if it already exists. Overwriting means
#' deleting and recreating the file from scratch. Note that if this option
#' is not specified and the output file already exists, it will be updated
#' in place.
#'
#' The documentation for [`gdalwarp`](https://gdal.org/en/stable/programs/gdalwarp.html)
#' describes additional command-line options related to spatial reference
#' systems, source nodata values, alpha bands, polygon cutlines as mask
#' including blending, and more.
#'
#' Mosaicing into an existing output file is supported if the output file
#' already exists. The spatial extent of the existing file will not be
#' modified to accommodate new data, so you may have to remove it in that
#' case, or use the `-overwrite` option.
#'
#' Command-line options are passed to `warp()` as a character vector. The
#' elements of the vector are the individual options followed by their
#' individual values, e.g.,
#' \preformatted{
#' cl_arg = c("-tr", "30", "30", "-r", "bilinear"))
#' }
#' to set the target pixel resolution to 30 x 30 in target georeferenced
#' units and use bilinear resampling.
#'
#' @param src_files Character vector of source file(s) to be reprojected.
#' @param dst_filename Character string. Filename of the output raster.
#' @param t_srs Character string. Target spatial reference system. Usually an
#' EPSG code ("EPSG:#####") or a well known text (WKT) SRS definition.
#' If empty string `""`, the spatial reference of `src_files[1]` will be
#' used (see Note).
#' @param cl_arg Optional character vector of command-line arguments to
#' \code{gdalwarp} in addition to `-t_srs` (see Details).
#' @param quiet Logical scalar. If `TRUE`, a progress bar will not be
#' displayed. Defaults to `FALSE`.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#'
#' @note
#' `warp()` can be used to reproject and also perform other processing such
#' as crop, resample, and mosaic.
#' This processing is generally done with a single function call by passing
#' arguments for the target (output) pixel resolution, extent, resampling
#' method, nodata value, format, and so forth.
#' If `warp()` is called with `t_srs` set to `""` (empty string),
#' the target spatial reference will be set to that of `src_files[1]`,
#' so that the processing options given in `cl_arg` will be performed without
#' reprojecting (in the case of one input raster or multiple inputs that
#' all use the same spatial reference system, otherwise would reproject
#' inputs to the SRS of `src_files[1]` when they are different).
#'
#' @seealso
#' [`GDALRaster-class`][GDALRaster], [srs_to_wkt()], [translate()]
#'
#' @examples
#' # reproject the elevation raster to NAD83 / CONUS Albers (EPSG:5070)
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#'
#' # command-line arguments for gdalwarp
#' # resample to 90-m resolution and keep pixels aligned:
#' args <- c("-tr", "90", "90", "-r", "cubic", "-tap")
#' # write to Erdas Imagine format (HFA) with compression:
#' args <- c(args, "-of", "HFA", "-co", "COMPRESSED=YES")
#'
#' alb83_file <- file.path(tempdir(), "storml_elev_alb83.img")
#' warp(elev_file, alb83_file, t_srs="EPSG:5070", cl_arg = args)
#'
#' ds <- new(GDALRaster, alb83_file)
#' ds$getDriverLongName()
#' ds$getProjectionRef()
#' ds$res()
#' ds$getStatistics(band=1, approx_ok=FALSE, force=TRUE)
#' ds$close()
#'
#' deleteDataset(alb83_file)
warp <- function(src_files, dst_filename, t_srs, cl_arg = NULL, quiet = FALSE) {
invisible(.Call(`_gdalraster_warp`, src_files, dst_filename, t_srs, cl_arg, quiet))
}
#' Create a color ramp
#'
#' `createColorRamp()` is a wrapper for `GDALCreateColorRamp()` in the GDAL
#' API. It automatically creates a color ramp from one color entry to another.
#' Output is an integer matrix in color table format for use with
#' [`GDALRaster$setColorTable()`][GDALRaster].
#'
#' @note
#' `createColorRamp()` could be called several times, using `rbind()` to
#' combine multiple ramps into the same color table. Possible duplicate rows
#' in the resulting table are not a problem when used in
#' `GDALRaster$setColorTable()` (i.e., when `end_color` of one ramp is the
#' same as `start_color` of the next ramp).
#'
#' @param start_index Integer start index (raster value).
#' @param start_color Integer vector of length three or four.
#' A color entry value to start the ramp (e.g., RGB values).
#' @param end_index Integer end index (raster value).
#' @param end_color Integer vector of length three or four.
#' A color entry value to end the ramp (e.g., RGB values).
#' @param palette_interp One of "Gray", "RGB" (the default), "CMYK" or "HLS"
#' describing interpretation of `start_color` and `end_color` values
#' (see \href{https://gdal.org/en/stable/user/raster_data_model.html#color-table}{GDAL
#' Color Table}).
#' @returns Integer matrix with five columns containing the color ramp from
#' `start_index` to `end_index`, with raster index values in column 1 and
#' color entries in columns 2:5).
#'
#' @seealso
#' [`GDALRaster$getColorTable()`][GDALRaster],
#' [`GDALRaster$getPaletteInterp()`][GDALRaster]
#'
#' @examples
#' # create a color ramp for tree canopy cover percent
#' # band 5 of an LCP file contains canopy cover
#' lcp_file <- system.file("extdata/storm_lake.lcp", package="gdalraster")
#' ds <- new(GDALRaster, lcp_file)
#' ds$getDescription(band=5)
#' ds$getMetadata(band=5, domain="")
#' ds$close()
#'
#' # create a GTiff file with Byte data type for the canopy cover band
#' # recode nodata -9999 to 255
#' tcc_file <- calc(expr = "ifelse(CANCOV == -9999, 255, CANCOV)",
#' rasterfiles = lcp_file,
#' bands = 5,
#' var.names = "CANCOV",
#' fmt = "GTiff",
#' dtName = "Byte",
#' nodata_value = 255,
#' setRasterNodataValue = TRUE)
#'
#' ds_tcc <- new(GDALRaster, tcc_file, read_only=FALSE)
#'
#' # create a color ramp from 0 to 100 and set as the color table
#' colors <- createColorRamp(start_index = 0,
#' start_color = c(211, 211, 211),
#' end_index = 100,
#' end_color = c(0, 100, 0))
#'
#' print(colors)
#' ds_tcc$setColorTable(band=1, col_tbl=colors, palette_interp="RGB")
#' ds_tcc$setRasterColorInterp(band=1, col_interp="Palette")
#'
#' # close and re-open the dataset in read_only mode
#' ds_tcc$open(read_only=TRUE)
#'
#' plot_raster(ds_tcc, interpolate=FALSE, legend=TRUE,
#' main="Storm Lake Tree Canopy Cover (%)")
#' ds_tcc$close()
#'
#' deleteDataset(tcc_file)
createColorRamp <- function(start_index, start_color, end_index, end_color, palette_interp = "RGB") {
.Call(`_gdalraster_createColorRamp`, start_index, start_color, end_index, end_color, palette_interp)
}
#' Copy a whole raster band efficiently
#'
#' `bandCopyWholeRaster()` copies the complete raster contents of one band to
#' another similarly configured band. The source and destination bands must
#' have the same xsize and ysize. The bands do not have to have the same data
#' type. It implements efficient copying, in particular "chunking" the copy in
#' substantial blocks. This is a wrapper for `GDALRasterBandCopyWholeRaster()`
#' in the GDAL API.
#'
#' @param src_filename Filename of the source raster.
#' @param src_band Band number in the source raster to be copied.
#' @param dst_filename Filename of the destination raster.
#' @param dst_band Band number in the destination raster to copy into.
#' @param options Optional list of transfer hints in a vector of `"NAME=VALUE"`
#' pairs. The currently supported `options` are:
#' * `"COMPRESSED=YES"` to force alignment on target dataset block sizes to
#' achieve best compression.
#' * `"SKIP_HOLES=YES"` to skip chunks that contain only empty blocks.
#' Empty blocks are blocks that are generally not physically present in the
#' file, and when read through GDAL, contain only pixels whose value is the
#' nodata value when it is set, or whose value is 0 when the nodata value is
#' not set. The query is done in an efficient way without reading the actual
#' pixel values (if implemented by the raster format driver, otherwise will
#' not be skipped).
#' @param quiet Logical scalar. If `TRUE`, a progress bar will not be
#' displayed. Defaults to `FALSE`.
#' @returns Logical indicating success (invisible \code{TRUE}).
#' An error is raised if the operation fails.
#'
#' @seealso
#' [`GDALRaster-class`][GDALRaster], [create()], [createCopy()],
#' [rasterFromRaster()]
#'
#' @examples
#' ## copy Landsat data from a single-band file to a new multi-band image
#' b5_file <- system.file("extdata/sr_b5_20200829.tif", package="gdalraster")
#' dst_file <- file.path(tempdir(), "sr_multi.tif")
#' rasterFromRaster(b5_file, dst_file, nbands=7, init=0)
#' opt <- c("COMPRESSED=YES", "SKIP_HOLES=YES")
#' bandCopyWholeRaster(b5_file, 1, dst_file, 5, options=opt)
#' ds <- new(GDALRaster, dst_file)
#' ds$getStatistics(band=5, approx_ok=FALSE, force=TRUE)
#' ds$close()
#'
#' deleteDataset(dst_file)
bandCopyWholeRaster <- function(src_filename, src_band, dst_filename, dst_band, options = NULL, quiet = FALSE) {
invisible(.Call(`_gdalraster_bandCopyWholeRaster`, src_filename, src_band, dst_filename, dst_band, options, quiet))
}
#' Delete named dataset
#'
#' `deleteDataset()` will attempt to delete the named dataset in a format
#' specific fashion. Full featured drivers will delete all associated files,
#' database objects, or whatever is appropriate. The default behavior when no
#' format specific behavior is provided is to attempt to delete all the files
#' that would be returned by `GDALRaster$getFileList()` on the dataset.
#' The named dataset should not be open in any existing `GDALRaster` objects
#' when `deleteDataset()` is called. Wrapper for `GDALDeleteDataset()` in the
#' GDAL API.
#'
#' @note
#' If `format` is set to an empty string `""` (the default) then the function
#' will try to identify the driver from `filename`. This is done internally in
#' GDAL by invoking the `Identify` method of each registered `GDALDriver` in
#' turn. The first driver that successful identifies the file name will be
#' returned. An error is raised if a format cannot be determined from the
#' passed file name.
#'
#' @param filename Filename to delete (should not be open in a `GDALRaster`
#' object).
#' @param format Raster format short name (e.g., "GTiff"). If set to empty
#' string `""` (the default), will attempt to guess the raster format from
#' `filename`.
#' @returns Logical `TRUE` if no error or `FALSE` on failure.
#'
#' @seealso
#' [`GDALRaster-class`][GDALRaster], [create()], [createCopy()],
#' [copyDatasetFiles()], [renameDataset()]
#'
#' @examples
#' b5_file <- system.file("extdata/sr_b5_20200829.tif", package="gdalraster")
#' b5_tmp <- file.path(tempdir(), "b5_tmp.tif")
#' file.copy(b5_file, b5_tmp)
#'
#' ds <- new(GDALRaster, b5_tmp)
#' ds$buildOverviews("BILINEAR", levels = c(2, 4, 8), bands = c(1))
#' files <- ds$getFileList()
#' print(files)
#' ds$close()
#' file.exists(files)
#' deleteDataset(b5_tmp)
#' file.exists(files)
deleteDataset <- function(filename, format = "") {
.Call(`_gdalraster_deleteDataset`, filename, format)
}
#' Rename a dataset
#'
#' `renameDataset()` renames a dataset in a format-specific way (e.g.,
#' rename associated files as appropriate). This could include moving the
#' dataset to a new directory or even a new filesystem.
#' The dataset should not be open in any existing `GDALRaster` objects
#' when `renameDataset()` is called. Wrapper for `GDALRenameDataset()` in the
#' GDAL API.
#'
#' @note
#' If `format` is set to an empty string `""` (the default) then the function
#' will try to identify the driver from `old_filename`. This is done
#' internally in GDAL by invoking the `Identify` method of each registered
#' `GDALDriver` in turn. The first driver that successful identifies the file
#' name will be returned. An error is raised if a format cannot be determined
#' from the passed file name.
#'
#' @param new_filename New name for the dataset.
#' @param old_filename Old name for the dataset (should not be open in a
#' `GDALRaster` object).
#' @param format Raster format short name (e.g., "GTiff"). If set to empty
#' string `""` (the default), will attempt to guess the raster format from
#' `old_filename`.
#' @returns Logical `TRUE` if no error or `FALSE` on failure.
#'
#' @seealso
#' [`GDALRaster-class`][GDALRaster], [create()], [createCopy()],
#' [deleteDataset()], [copyDatasetFiles()]
#'
#' @examples
#' b5_file <- system.file("extdata/sr_b5_20200829.tif", package="gdalraster")
#' b5_tmp <- file.path(tempdir(), "b5_tmp.tif")
#' file.copy(b5_file, b5_tmp)
#'
#' ds <- new(GDALRaster, b5_tmp)
#' ds$buildOverviews("BILINEAR", levels = c(2, 4, 8), bands = c(1))
#' ds$getFileList()
#' ds$close()
#' b5_tmp2 <- file.path(tempdir(), "b5_tmp_renamed.tif")
#' renameDataset(b5_tmp2, b5_tmp)
#' ds <- new(GDALRaster, b5_tmp2)
#' ds$getFileList()
#' ds$close()
#'
#' deleteDataset(b5_tmp2)
renameDataset <- function(new_filename, old_filename, format = "") {
.Call(`_gdalraster_renameDataset`, new_filename, old_filename, format)
}
#' Copy the files of a dataset
#'
#' `copyDatasetFiles()` copies all the files associated with a dataset.
#' Wrapper for `GDALCopyDatasetFiles()` in the GDAL API.
#'
#' @note
#' If `format` is set to an empty string `""` (the default) then the function
#' will try to identify the driver from `old_filename`. This is done
#' internally in GDAL by invoking the `Identify` method of each registered
#' `GDALDriver` in turn. The first driver that successful identifies the file
#' name will be returned. An error is raised if a format cannot be determined
#' from the passed file name.
#'
#' @param new_filename New name for the dataset (copied to).
#' @param old_filename Old name for the dataset (copied from).
#' @param format Raster format short name (e.g., "GTiff"). If set to empty
#' string `""` (the default), will attempt to guess the raster format from
#' `old_filename`.
#' @returns Logical `TRUE` if no error or `FALSE` on failure.
#'
#' @seealso
#' [`GDALRaster-class`][GDALRaster], [create()], [createCopy()],
#' [deleteDataset()], [renameDataset()], [vsi_copy_file()]
#'
#' @examples
#' lcp_file <- system.file("extdata/storm_lake.lcp", package="gdalraster")
#' ds <- new(GDALRaster, lcp_file)
#' ds$getFileList()
#' ds$close()
#'
#' lcp_tmp <- file.path(tempdir(), "storm_lake_copy.lcp")
#' copyDatasetFiles(lcp_tmp, lcp_file)
#' ds_copy <- new(GDALRaster, lcp_tmp)
#' ds_copy$getFileList()
#' ds_copy$close()
#'
#' deleteDataset(lcp_tmp)
copyDatasetFiles <- function(new_filename, old_filename, format = "") {
.Call(`_gdalraster_copyDatasetFiles`, new_filename, old_filename, format)
}
#' Identify the GDAL driver that can open a dataset
#'
#' `identifyDriver()` will try to identify the driver that can open the passed
#' file name by invoking the Identify method of each registered GDALDriver in
#' turn. The short name of the first driver that successfully identifies the
#' file name will be returned as a character string. If all drivers fail then
#' `NULL` is returned.
#' Wrapper of `GDALIdentifyDriverEx()` in the GDAL C API.
#'
#' @note
#' In order to reduce the need for such searches to touch the file system
#' machinery of the operating system, it is possible to give an optional list
#' of files. This is the list of all files at the same level in the file
#' system as the target file, including the target file. The filenames should
#' not include any path components. If the target object does not have
#' filesystem semantics then the file list should be `NULL`.
#'
#' At least one of the `raster` or `vector` arguments must be `TRUE`.
#'
#' @param filename Character string containing the name of the file to access.
#' This may not refer to a physical file, but instead contain information for
#' the driver on how to access a dataset (e.g., connection string, URL, etc.)
#' @param raster Logical value indicating whether to include raster format
#' drivers in the search, `TRUE` by default. May be set to `FALSE` to include
#' only vector drivers.
#' @param vector Logical value indicating whether to include vector format
#' drivers in the search, `TRUE` by default. May be set to `FALSE` to include
#' only raster drivers.
#' @param allowed_drivers Optional character vector of driver short names
#' that must be considered. Set to `NULL` to consider all candidate drivers
#' (the default).
#' @param file_list Optional character vector of filenames, including those
#' that are auxiliary to the main filename (see Note). May contain the input
#' `filename` but this is not required. Defaults to `NULL`.
#' @returns A character string with the short name of the first driver that
#' successfully identifies the input file name, or `NULL` on failure.
#'
#' @seealso
#' [gdal_formats()]
#'
#' @examples
#' src <- system.file("extdata/ynp_fires_1984_2022.gpkg", package="gdalraster")
#'
#' identifyDriver(src) |> gdal_formats()
identifyDriver <- function(filename, raster = TRUE, vector = TRUE, allowed_drivers = NULL, file_list = NULL) {
.Call(`_gdalraster_identifyDriver`, filename, raster, vector, allowed_drivers, file_list)
}
#' Return the list of creation options of a GDAL driver as XML string
#'
#' Called from and documented in R/gdal_helpers.R
#' @noRd
.getCreationOptions <- function(format) {
.Call(`_gdalraster_getCreationOptions`, format)
}
#' Add a file inside a new or existing ZIP file
#' Mainly for create/append to Seek-Optimized ZIP
#'
#' @noRd
.addFileInZip <- function(zip_filename, overwrite, archive_filename, in_filename, options, quiet) {
.Call(`_gdalraster_addFileInZip`, zip_filename, overwrite, archive_filename, in_filename, options, quiet)
}
#' Copy a source file to a target filename
#'
#' `vsi_copy_file()` is a wrapper for `VSICopyFile()` in the GDAL Common
#' Portability Library. The GDAL VSI functions allow virtualization of disk
#' I/O so that non file data sources can be made to appear as files.
#' See \url{https://gdal.org/en/stable/user/virtual_file_systems.html}.
#' Requires GDAL >= 3.7.
#'
#' @details
#' The following copies are made fully on the target server, without local
#' download from source and upload to target:
#' * /vsis3/ -> /vsis3/
#' * /vsigs/ -> /vsigs/
#' * /vsiaz/ -> /vsiaz/
#' * /vsiadls/ -> /vsiadls/
#' * any of the above or /vsicurl/ -> /vsiaz/ (starting with GDAL 3.8)
#'
#' @param src_file Character string. Filename of the source file.
#' @param target_file Character string. Filename of the target file.
#' @param show_progress Logical scalar. If `TRUE`, a progress bar will be
#' displayed (the size of `src_file` will be retrieved in GDAL with
#' `VSIStatL()`). Default is `FALSE`.
#' @returns `0` on success or `-1` on an error.
#'
#' @note
#' If `target_file` has the form /vsizip/foo.zip/bar, the default options
#' described for the function `addFilesInZip()` will be in effect.
#'
#' @seealso
#' [copyDatasetFiles()], [vsi_stat()], [vsi_sync()]
#'
#' @examples
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' tmp_file <- "/vsimem/elev_temp.tif"
#'
#' # Requires GDAL >= 3.7
#' if (as.integer(gdal_version()[2]) >= 3070000) {
#' result <- vsi_copy_file(elev_file, tmp_file)
#' print(result)
#' print(vsi_stat(tmp_file, "size"))
#'
#' vsi_unlink(tmp_file)
#' }
vsi_copy_file <- function(src_file, target_file, show_progress = FALSE) {
.Call(`_gdalraster_vsi_copy_file`, src_file, target_file, show_progress)
}
#' Clean cache associated with /vsicurl/ and related file systems
#'
#' `vsi_curl_clear_cache()` cleans the local cache associated with /vsicurl/
#' (and related file systems). This function is a wrapper for
#' `VSICurlClearCache()` and `VSICurlPartialClearCache()` in the GDAL Common
#' Portability Library. See Details for the GDAL documentation.
#'
#' @details
#' /vsicurl/ (and related file systems like /vsis3/, /vsigs/, /vsiaz/,
#' /vsioss/, /vsiswift/) cache a number of metadata and data for faster
#' execution in read-only scenarios. But when the content on the server-side
#' may change during the same process, those mechanisms can prevent opening
#' new files, or give an outdated version of them.
#' If `partial = TRUE`, cleans the local cache associated for a given filename
#' (and its subfiles and subdirectories if it is a directory).
#'
#' @param partial Logical scalar. Whether to clear the cache only for a given
#' filename (see Details).
#' @param file_prefix Character string. Filename prefix to use if
#' `partial = TRUE`.
#' @param quiet Logical scalar. `TRUE` (the default) to wrap the API call in
#' a quiet error handler, or `FALSE` to print any potential error messages to
#' the console.
#' @returns No return value, called for side effects.
#'
#' @examples
#' vsi_curl_clear_cache()
vsi_curl_clear_cache <- function(partial = FALSE, file_prefix = "", quiet = TRUE) {
invisible(.Call(`_gdalraster_vsi_curl_clear_cache`, partial, file_prefix, quiet))
}
#' Read names in a directory
#'
#' `vsi_read_dir()` abstracts access to directory contents. It returns a
#' character vector containing the names of files and directories in this
#' directory. With `recursive = TRUE`, reads the list of entries in the
#' directory and subdirectories.
#' This function is a wrapper for `VSIReadDirEx()` and `VSIReadDirRecursive()`
#' in the GDAL Common Portability Library.
#'
#' @param path Character string. The relative or absolute path of a
#' directory to read.
#' @param max_files Integer scalar. The maximum number of files after which to
#' stop, or 0 for no limit (see Note). Ignored if `recursive = TRUE`.
#' @param recursive Logical scalar. `TRUE` to read the directory and its
#' subdirectories. Defaults to `FALSE`.
#' @param all_files Logical scalar. If `FALSE` (the default), only the names
#' of visible files are returned (following Unix-style visibility, that is
#' files whose name does not start with a dot). If `TRUE`, all file names
#' will be returned.
#' @returns A character vector containing the names of files and directories
#' in the directory given by `path`. The listing is in alphabetical order, and
#' does not include the special entries '.' and '..' even if they are present
#' in the directory. An empty string (`""`) is returned if `path` does not
#' exist.
#'
#' @note
#' If `max_files` is set to a positive number, directory listing will stop
#' after that limit has been reached. Note that to indicate truncation, at
#' least one element more than the `max_files` limit will be returned. If the
#' length of the returned character vector is lesser or equal to `max_files`,
#' then no truncation occurred. The `max_files` parameter is ignored when
#' `recursive = TRUE`.
#'
#' @seealso
#' [vsi_mkdir()], [vsi_rmdir()], [vsi_stat()], [vsi_sync()]
#'
#' @examples
#' # regular file system for illustration
#' data_dir <- system.file("extdata", package="gdalraster")
#' vsi_read_dir(data_dir)
vsi_read_dir <- function(path, max_files = 0L, recursive = FALSE, all_files = FALSE) {
.Call(`_gdalraster_vsi_read_dir`, path, max_files, recursive, all_files)
}
#' Synchronize a source file/directory with a target file/directory
#'
#' `vsi_sync()` is a wrapper for `VSISync()` in the GDAL Common Portability
#' Library. The GDAL documentation is given in Details.
#'
#' @details
#' `VSISync()` is an analog of the Linux `rsync` utility. In the current
#' implementation, `rsync` would be more efficient for local file copying,
#' but `VSISync()` main interest is when the source or target is a remote
#' file system like /vsis3/ or /vsigs/, in which case it can take into account
#' the timestamps of the files (or optionally the ETag/MD5Sum) to avoid
#' unneeded copy operations.
#' This is only implemented efficiently for:
#' * local filesystem <--> remote filesystem
#' * remote filesystem <--> remote filesystem (starting with GDAL 3.1)\cr
#' Where the source and target remote filesystems are the same and one of
#' /vsis3/, /vsigs/ or /vsiaz/. Or when the target is /vsiaz/ and the source
#' is /vsis3/, /vsigs/, /vsiadls/ or /vsicurl/ (starting with GDAL 3.8)
#'
#' Similarly to `rsync` behavior, if the source filename ends with a slash, it
#' means that the content of the directory must be copied, but not the
#' directory name. For example, assuming "/home/even/foo" contains a file
#' "bar", `VSISync("/home/even/foo/", "/mnt/media", ...)` will create a
#' "/mnt/media/bar" file.
#' Whereas `VSISync("/home/even/foo", "/mnt/media", ...)` will create a
#' "/mnt/media/foo" directory which contains a bar file.
#'
#' The `options` argument accepts a character vector of name=value pairs.
#' Currently accepted options are:\cr
#' * `RECURSIVE=NO` (the default is `YES`)
#' * `SYNC_STRATEGY=TIMESTAMP/ETAG/OVERWRITE`. Determines which criterion is
#' used to determine if a target file must be replaced when it already exists
#' and has the same file size as the source. Only applies for a source or
#' target being a network filesystem.
#' The default is `TIMESTAMP` (similarly to how 'aws s3 sync' works), that is
#' to say that for an upload operation, a remote file is replaced if it has a
#' different size or if it is older than the source. For a download operation,
#' a local file is replaced if it has a different size or if it is newer than
#' the remote file.
#' The `ETAG` strategy assumes that the ETag metadata of the remote file is
#' the MD5Sum of the file content, which is only true in the case of /vsis3/
#' for files not using KMS server side encryption and uploaded in a single PUT
#' operation (so smaller than 50 MB given the default used by GDAL). Only to
#' be used for /vsis3/, /vsigs/ or other filesystems using a MD5Sum as ETAG.
#' The `OVERWRITE` strategy (GDAL >= 3.2) will always overwrite the target
#' file with the source one.\cr
#' * `NUM_THREADS=integer`. Number of threads to use for parallel file
#' copying. Only use for when /vsis3/, /vsigs/, /vsiaz/ or /vsiadls/ is
#' in source or target. The default is 10 since GDAL 3.3.\cr
#' * `CHUNK_SIZE=integer`. Maximum size of chunk (in bytes) to use to split
#' large objects when downloading them from /vsis3/, /vsigs/, /vsiaz/
#' or /vsiadls/ to local file system, or for upload to /vsis3/, /vsiaz/ or
#' /vsiadls/ from local file system. Only used if `NUM_THREADS > 1`.
#' For upload to /vsis3/, this chunk size must be set at least to 5 MB. The
#' default is 8 MB since GDAL 3.3.\cr
#' * `x-amz-KEY=value`. (GDAL >= 3.5) MIME header to pass during creation of a
#' /vsis3/ object.\cr
#' * `x-goog-KEY=value`. (GDAL >= 3.5) MIME header to pass during creation of a
#' /vsigs/ object.\cr
#' * `x-ms-KEY=value`. (GDAL >= 3.5) MIME header to pass during creation of a
#' /vsiaz/ or /vsiadls/ object.
#'
#' @param src Character string. Source file or directory.
#' @param target Character string. Target file or directory.
#' @param show_progress Logical scalar. If `TRUE`, a progress bar will be
#' displayed. Defaults to `FALSE`.
#' @param options Character vector of `NAME=VALUE` pairs (see Details).
#' @returns Logical scalar, `TRUE` on success or `FALSE` on an error.
#'
#' @seealso
#' [copyDatasetFiles()], [vsi_copy_file()]
#'
#' @examples
#' \dontrun{
#' # sample-data is a directory in the git repository for gdalraster that is
#' # not included in the R package:
#' # https://github.com/USDAForestService/gdalraster/tree/main/sample-data
#' # A copy of sample-data in an AWS S3 bucket, and a partial copy in an
#' # Azure Blob container, were used to generate the example below.
#'
#' src <- "/vsis3/gdalraster-sample-data/"
#' # s3://gdalraster-sample-data is not public, set credentials
#' set_config_option("AWS_ACCESS_KEY_ID", "xxxxxxxxxxxxxx")
#' set_config_option("AWS_SECRET_ACCESS_KEY", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
#' vsi_read_dir(src)
#' #> [1] "README.md"
#' #> [2] "bl_mrbl_ng_jul2004_rgb_720x360.tif"
#' #> [3] "blue_marble_ng_neo_metadata.xml"
#' #> [4] "landsat_c2ard_sr_mt_hood_jul2022_utm.json"
#' #> [5] "landsat_c2ard_sr_mt_hood_jul2022_utm.tif"
#' #> [6] "lf_elev_220_metadata.html"
#' #> [7] "lf_elev_220_mt_hood_utm.tif"
#' #> [8] "lf_fbfm40_220_metadata.html"
#' #> [9] "lf_fbfm40_220_mt_hood_utm.tif"
#'
#' dst <- "/vsiaz/sampledata"
#' set_config_option("AZURE_STORAGE_CONNECTION_STRING",
#' "<connection_string_for_gdalraster_account>")
#' vsi_read_dir(dst)
#' #> [1] "lf_elev_220_metadata.html" "lf_elev_220_mt_hood_utm.tif"
#'
#' # GDAL VSISync() supports direct copy for /vsis3/ -> /vsiaz/ (GDAL >= 3.8)
#' result <- vsi_sync(src, dst, show_progress = TRUE)
#' #> 0...10...20...30...40...50...60...70...80...90...100 - done.
#' print(result)
#' #> [1] TRUE
#' vsi_read_dir(dst)
#' #> [1] "README.md"
#' #> [2] "bl_mrbl_ng_jul2004_rgb_720x360.tif"
#' #> [3] "blue_marble_ng_neo_metadata.xml"
#' #> [4] "landsat_c2ard_sr_mt_hood_jul2022_utm.json"
#' #> [5] "landsat_c2ard_sr_mt_hood_jul2022_utm.tif"
#' #> [6] "lf_elev_220_metadata.html"
#' #> [7] "lf_elev_220_mt_hood_utm.tif"
#' #> [8] "lf_fbfm40_220_metadata.html"
#' #> [9] "lf_fbfm40_220_mt_hood_utm.tif"
#' }
vsi_sync <- function(src, target, show_progress = FALSE, options = NULL) {
.Call(`_gdalraster_vsi_sync`, src, target, show_progress, options)
}
#' Create a directory
#'
#' `vsi_mkdir()` creates a new directory with the indicated mode.
#' For POSIX-style systems, the mode is modified by the file creation mask
#' (umask). However, some file systems and platforms may not use umask, or
#' they may ignore the mode completely. So a reasonable cross-platform
#' default mode value is `0755`.
#' With `recursive = TRUE`, creates a directory and all its ancestors.
#' This function is a wrapper for `VSIMkdir()` and `VSIMkdirRecursive()` in
#' the GDAL Common Portability Library.
#'
#' @param path Character string. The path to the directory to create.
#' @param mode Character string. The permissions mode in octal with prefix
#' `0`, e.g., `"0755"` (the default).
#' @param recursive Logical scalar. `TRUE` to create the directory and its
#' ancestors. Defaults to `FALSE`.
#' @returns `0` on success or `-1` on an error.
#'
#' @seealso
#' [vsi_read_dir()], [vsi_rmdir()]
#'
#' @examples
#' new_dir <- file.path(tempdir(), "newdir")
#' vsi_mkdir(new_dir)
#' vsi_stat(new_dir, "type")
#' vsi_rmdir(new_dir)
vsi_mkdir <- function(path, mode = "0755", recursive = FALSE) {
.Call(`_gdalraster_vsi_mkdir`, path, mode, recursive)
}
#' Delete a directory
#'
#' `vsi_rmdir()` deletes a directory object from the file system. On some
#' systems the directory must be empty before it can be deleted.
#' With `recursive = TRUE`, deletes a directory object and its content from
#' the file system.
#' This function goes through the GDAL `VSIFileHandler` virtualization and may
#' work on unusual filesystems such as in memory.
#' It is a wrapper for `VSIRmdir()` and `VSIRmdirRecursive()` in the GDAL
#' Common Portability Library.
#'
#' @param path Character string. The path to the directory to be deleted.
#' @param recursive Logical scalar. `TRUE` to delete the directory and its
#' content. Defaults to `FALSE`.
#' @returns `0` on success or `-1` on an error.
#'
#' @note
#' /vsis3/ has an efficient implementation for deleting recursively. Starting
#' with GDAL 3.4, /vsigs/ has an efficient implementation for deleting
#' recursively, provided that OAuth2 authentication is used.
#'
#' @seealso
#' [deleteDataset()], [vsi_mkdir()], [vsi_read_dir()], [vsi_unlink()]
#'
#' @examples
#' new_dir <- file.path(tempdir(), "newdir")
#' vsi_mkdir(new_dir)
#' vsi_rmdir(new_dir)
vsi_rmdir <- function(path, recursive = FALSE) {
.Call(`_gdalraster_vsi_rmdir`, path, recursive)
}
#' Delete a file
#'
#' `vsi_unlink()` deletes a file object from the file system.
#' This function goes through the GDAL `VSIFileHandler` virtualization and may
#' work on unusual filesystems such as in memory.
#' It is a wrapper for `VSIUnlink()` in the GDAL Common Portability Library.
#' Analog of the POSIX `unlink()` function.
#'
#' @param filename Character string. The path of the file to be deleted.
#' @returns `0` on success or `-1` on an error.
#'
#' @seealso
#' [deleteDataset()], [vsi_rmdir()], [vsi_unlink_batch()]
#'
#' @examples
#' # regular file system for illustration
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' tmp_file <- file.path(tempdir(), "tmp.tif")
#' file.copy(elev_file, tmp_file)
#' vsi_stat(tmp_file)
#' vsi_unlink(tmp_file)
#' vsi_stat(tmp_file)
vsi_unlink <- function(filename) {
.Call(`_gdalraster_vsi_unlink`, filename)
}
#' Delete several files in a batch
#'
#' `vsi_unlink_batch()` deletes a list of files passed in a character vector.
#' All files should belong to the same file system handler.
#' This is implemented efficiently for /vsis3/ and /vsigs/ (provided for
#' /vsigs/ that OAuth2 authentication is used).
#' This function is a wrapper for `VSIUnlinkBatch()` in the GDAL Common
#' Portability Library.
#'
#' @param filenames Character vector. The list of files to delete.
#' @returns Logical vector of `length(filenames)` with values depending
#' on the success of deletion of the corresponding file.
#' `NULL` might be returned in case of a more general error (for example,
#' files belonging to different file system handlers).
#'
#' @seealso
#' [deleteDataset()], [vsi_rmdir()], [vsi_unlink()]
#'
#' @examples
#' # regular file system for illustration
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' tcc_file <- system.file("extdata/storml_tcc.tif", package="gdalraster")
#'
#' tmp_elev <- file.path(tempdir(), "tmp_elev.tif")
#' file.copy(elev_file, tmp_elev)
#' tmp_tcc <- file.path(tempdir(), "tmp_tcc.tif")
#' file.copy(tcc_file, tmp_tcc)
#' vsi_unlink_batch(c(tmp_elev, tmp_tcc))
vsi_unlink_batch <- function(filenames) {
.Call(`_gdalraster_vsi_unlink_batch`, filenames)
}
#' Get filesystem object info
#'
#' `vsi_stat()` fetches status information about a filesystem object (file,
#' directory, etc).
#' This function goes through the GDAL `VSIFileHandler` virtualization and may
#' work on unusual filesystems such as in memory.
#' It is a wrapper for `VSIStatExL()` in the GDAL Common Portability Library.
#' Analog of the POSIX `stat()` function.
#'
#' @param filename Character string. The path of the filesystem object to be
#' queried.
#' @param info Character string. The type of information to fetch, one of
#' `"exists"` (the default), `"type"` or `"size"`.
#' @returns If `info = "exists"`, returns logical `TRUE` if the file system
#' object exists, otherwise `FALSE`. If `info = "type"`, returns a character
#' string with one of `"file"` (regular file), `"dir"` (directory),
#' `"symlink"` (symbolic link), or empty string (`""`). If `info = "size"`,
#' returns the file size in bytes (as `bit64::integer64` type), or `-1` if an
#' error occurs.
#'
#' @note
#' For portability, `vsi_stat()` supports a subset of `stat()`-type
#' information for filesystem objects. This function is primarily intended
#' for use with GDAL virtual file systems (e.g., URLs, cloud storage systems,
#' ZIP/GZip/7z/RAR archives, in-memory files).
#' The base R function `utils::file_test()` could be used instead for file
#' tests on regular local filesystems.
#'
#' @seealso
#' GDAL Virtual File Systems:\cr
#' \url{https://gdal.org/en/stable/user/virtual_file_systems.html}
#'
#' @examples
#' data_dir <- system.file("extdata", package="gdalraster")
#' vsi_stat(data_dir)
#' vsi_stat(data_dir, "type")
#' # stat() on a directory doesn't return the sum of the file sizes in it,
#' # but rather how much space is used by the directory entry
#' vsi_stat(data_dir, "size")
#'
#' elev_file <- file.path(data_dir, "storml_elev.tif")
#' vsi_stat(elev_file)
#' vsi_stat(elev_file, "type")
#' vsi_stat(elev_file, "size")
#'
#' nonexistent <- file.path(data_dir, "nonexistent.tif")
#' vsi_stat(nonexistent)
#' vsi_stat(nonexistent, "type")
#' vsi_stat(nonexistent, "size")
#'
#' # /vsicurl/ file system handler
#' base_url <- "https://raw.githubusercontent.com/usdaforestservice/"
#' f <- "gdalraster/main/sample-data/landsat_c2ard_sr_mt_hood_jul2022_utm.tif"
#' url_file <- paste0("/vsicurl/", base_url, f)
#'
#' vsi_stat(url_file)
#' vsi_stat(url_file, "type")
#' vsi_stat(url_file, "size")
vsi_stat <- function(filename, info = "exists") {
.Call(`_gdalraster_vsi_stat`, filename, info)
}
#' Rename a file
#'
#' `vsi_rename()` renames a file object in the file system. The GDAL
#' documentation states it should be possible to rename a file onto a new
#' filesystem, but it is safest if this function is only used to rename files
#' that remain in the same directory.
#' This function goes through the GDAL `VSIFileHandler` virtualization and may
#' work on unusual filesystems such as in memory.
#' It is a wrapper for `VSIRename()` in the GDAL Common Portability Library.
#' Analog of the POSIX `rename()` function.
#'
#' @param oldpath Character string. The name of the file to be renamed.
#' @param newpath Character string. The name the file should be given.
#' @returns `0` on success or `-1` on an error.
#'
#' @seealso
#' [renameDataset()], [vsi_copy_file()]
#'
#' @examples
#' # regular file system for illustration
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' tmp_file <- tempfile(fileext = ".tif")
#' file.copy(elev_file, tmp_file)
#' new_file <- file.path(dirname(tmp_file), "storml_elev_copy.tif")
#' vsi_rename(tmp_file, new_file)
#' vsi_stat(new_file)
#' vsi_unlink(new_file)
vsi_rename <- function(oldpath, newpath) {
.Call(`_gdalraster_vsi_rename`, oldpath, newpath)
}
#' Return the list of virtual file system handlers currently registered
#'
#' `vsi_get_fs_prefixes()` returns the list of prefixes for virtual file
#' system handlers currently registered (e.g., `"/vsimem/"`, `"/vsicurl/"`,
#' etc). Wrapper for `VSIGetFileSystemsPrefixes()` in the GDAL API.
#'
#' @returns Character vector containing prefixes of the virtual file system
#' handlers.
#'
#' @seealso
#' [vsi_get_fs_options()]
#'
#' \url{https://gdal.org/en/stable/user/virtual_file_systems.html}
#'
#' @examples
#' vsi_get_fs_prefixes()
vsi_get_fs_prefixes <- function() {
.Call(`_gdalraster_vsi_get_fs_prefixes`)
}
#' Return the list of options associated with a virtual file system handler
#' as a serialized XML string.
#'
#' Called from and documented in R/gdal_helpers.R
#' @noRd
.vsi_get_fs_options <- function(filename) {
.Call(`_gdalraster__vsi_get_fs_options`, filename)
}
#' Return whether the filesystem supports sequential write
#'
#' `vsi_supports_seq_write()` returns whether the filesystem supports
#' sequential write.
#' Wrapper for `VSISupportsSequentialWrite()` in the GDAL API.
#'
#' @param filename Character string. The path of the filesystem object to be
#' tested.
#' @param allow_local_tmpfile Logical scalar. `TRUE` if the filesystem is
#' allowed to use a local temporary file before uploading to the target
#' location.
#' @returns Logical scalar. `TRUE` if sequential write is supported.
#'
#' @note
#' The location GDAL uses for temporary files can be forced via the
#' `CPL_TMPDIR` configuration option.
#'
#' @seealso
#' [vsi_supports_rnd_write()]
#'
#' @examples
#' # Requires GDAL >= 3.6
#' if (as.integer(gdal_version()[2]) >= 3060000)
#' vsi_supports_seq_write("/vsimem/test-mem-file.gpkg", TRUE)
vsi_supports_seq_write <- function(filename, allow_local_tmpfile) {
.Call(`_gdalraster_vsi_supports_seq_write`, filename, allow_local_tmpfile)
}
#' Return whether the filesystem supports random write
#'
#' `vsi_supports_rnd_write()` returns whether the filesystem supports
#' random write.
#' Wrapper for `VSISupportsRandomWrite()` in the GDAL API.
#'
#' @param filename Character string. The path of the filesystem object to be
#' tested.
#' @param allow_local_tmpfile Logical scalar. `TRUE` if the filesystem is
#' allowed to use a local temporary file before uploading to the target
#' location.
#' @returns Logical scalar. `TRUE` if random write is supported.
#'
#' @note
#' The location GDAL uses for temporary files can be forced via the
#' `CPL_TMPDIR` configuration option.
#'
#' @seealso
#' [vsi_supports_seq_write()]
#'
#' @examples
#' # Requires GDAL >= 3.6
#' if (as.integer(gdal_version()[2]) >= 3060000)
#' vsi_supports_rnd_write("/vsimem/test-mem-file.gpkg", TRUE)
vsi_supports_rnd_write <- function(filename, allow_local_tmpfile) {
.Call(`_gdalraster_vsi_supports_rnd_write`, filename, allow_local_tmpfile)
}
#' Return free disk space available on the filesystem
#'
#' `vsi_get_disk_free_space()` returns the free disk space available on the
#' filesystem. Wrapper for `VSIGetDiskFreeSpace()` in the GDAL Common
#' Portability Library.
#'
#' @param path Character string. A directory of the filesystem to query.
#' @returns Numeric scalar. The free space in bytes (as `bit64::integer64`
#' type), or `-1` in case of error.
#'
#' @examples
#' tmp_dir <- file.path("/vsimem", "tmpdir")
#' vsi_mkdir(tmp_dir)
#' vsi_get_disk_free_space(tmp_dir)
#' vsi_rmdir(tmp_dir)
vsi_get_disk_free_space <- function(path) {
.Call(`_gdalraster_vsi_get_disk_free_space`, path)
}
#' Set a path specific option for a given path prefix
#'
#' `vsi_set_path_option()` sets a path specific option for a given path
#' prefix. Such an option is typically, but not limited to, setting
#' credentials for a virtual file system.
#' Wrapper for `VSISetPathSpecificOption()` in the GDAL Common Portability
#' Library. Requires GDAL >= 3.6.
#'
#' @details
#' Options may also be set with `set_config_option()`, but
#' `vsi_set_path_option()` allows specifying them with a granularity at the
#' level of a file path. This makes it easier if using the same virtual file
#' system but with different credentials (e.g., different credentials for
#' buckets "/vsis3/foo" and "/vsis3/bar"). This is supported for the following
#' virtual file systems: /vsis3/, /vsigs/, /vsiaz/, /vsioss/, /vsiwebhdfs,
#' /vsiswift.
#'
#' @param path_prefix Character string. A path prefix of a virtual file system
#' handler. Typically of the form `/vsiXXX/bucket`.
#' @param key Character string. Option key.
#' @param value Character string. Option value. Passing `value = ""` (empty
#' string) will unset a value previously set by `vsi_set_path_option()`.
#' @returns No return value, called for side effect.
#'
#' @note
#' Setting options for a path starting with /vsiXXX/ will also apply for
#' /vsiXXX_streaming/ requests.
#'
#' No particular care is taken to store options in RAM in a secure way.
#' So they might accidentally hit persistent storage if swapping occurs,
#' or someone with access to the memory allocated by the process may be
#' able to read them.
#'
#' @seealso
#' [set_config_option()], [vsi_clear_path_options()]
vsi_set_path_option <- function(path_prefix, key, value) {
invisible(.Call(`_gdalraster_vsi_set_path_option`, path_prefix, key, value))
}
#' Clear path specific configuration options
#'
#' `vsi_clear_path_options()` clears path specific options previously set
#' with `vsi_set_path_option()`.
#' Wrapper for `VSIClearPathSpecificOptions()` in the GDAL Common Portability
#' Library. Requires GDAL >= 3.6.
#'
#' @param path_prefix Character string. If set to `""` (empty string), all
#' path specific options are cleared. If set to a path prefix, only those
#' options set with `vsi_set_path_option(path_prefix, ...)` will be cleared.
#' @returns No return value, called for side effect.
#'
#' @note
#' No particular care is taken to remove options from RAM in a secure way.
#'
#' @seealso
#' [vsi_set_path_option()]
vsi_clear_path_options <- function(path_prefix) {
invisible(.Call(`_gdalraster_vsi_clear_path_options`, path_prefix))
}
#' Get metadata on files
#'
#' `vsi_get_file_metadata()` returns metadata for file system objects.
#' Implemented for network-like filesystems. Starting with GDAL 3.7,
#' implemented for /vsizip/ with SOZip metadata.
#' Wrapper of `VSIGetFileMetadata()` in the GDAL Common Portability Library.
#'
#' @details
#' The metadata available depends on the file system. The following are
#' supported as of GDAL 3.9:
#' * HEADERS: to get HTTP headers for network-like filesystems (/vsicurl/,
#' /vsis3/, /vsgis/, etc).
#' * TAGS: for /vsis3/, to get S3 Object tagging information. For /vsiaz/,
#' to get blob tags.
#' * STATUS: specific to /vsiadls/: returns all system-defined properties
#' for a path (seems in practice to be a subset of HEADERS).
#' * ACL: specific to /vsiadls/ and /vsigs/: returns the access control list
#' for a path. For /vsigs/, a single `XML=xml_content` string is returned.
#' * METADATA: specific to /vsiaz/: blob metadata (this will be a subset of
#' what `domain=HEADERS` returns).
#' * ZIP: specific to /vsizip/: to obtain ZIP specific metadata, in
#' particular if a file is SOZIP-enabled (`SOZIP_VALID=YES`).
#'
#' @param filename Character string. The path of the file system object to be
#' queried.
#' @param domain Character string. Metadata domain to query. Depends on the
#' file system, see Details.
#' @returns A named list of values, or `NULL` in case of error or empty list.
#'
#' @seealso
#' [vsi_stat()], [addFilesInZip()]
#'
#' @examples
#' # create an SOZip-enabled file and validate
#' # Requires GDAL >= 3.7
#' f <- system.file("extdata/ynp_fires_1984_2022.gpkg", package="gdalraster")
#'
#' if (as.integer(gdal_version()[2]) >= 3070000) {
#' zip_file <- tempfile(fileext=".zip")
#' addFilesInZip(zip_file, f, full_paths=FALSE, sozip_enabled="YES")
#' zip_vsi <- file.path("/vsizip", zip_file)
#' print("Files in zip archive:")
#' print(vsi_read_dir(zip_vsi))
#' print("SOZip metadata:")
#' print(vsi_get_file_metadata(zip_vsi, domain="ZIP"))
#'
#' vsi_unlink(zip_file)
#' }
vsi_get_file_metadata <- function(filename, domain) {
.Call(`_gdalraster_vsi_get_file_metadata`, filename, domain)
}
#' @noRd
NULL
#' @noRd
NULL
#' @noRd
NULL
#' @noRd
NULL
#' get GEOS version
#' @noRd
.getGEOSVersion <- function() {
.Call(`_gdalraster_getGEOSVersion`)
}
#' Is GEOS available?
#'
#' `has_geos()` returns a logical value indicating whether GDAL was built
#' against the GEOS library. GDAL built with GEOS is a system requirement
#' as of `gdalraster` 1.10.0, so this function will always return `TRUE`
#' (may be removed in a future version).
#'
#' @return Logical. `TRUE` if GEOS is available, otherwise `FALSE`.
#'
#' @examples
#' has_geos()
has_geos <- function() {
.Call(`_gdalraster_has_geos`)
}
#' @noRd
.g_create <- function(xy, geom_type) {
.Call(`_gdalraster_g_create`, xy, geom_type)
}
#' @noRd
.g_add_geom <- function(sub_geom, container) {
.Call(`_gdalraster_g_add_geom`, sub_geom, container)
}
#' @noRd
.g_is_valid <- function(geom) {
.Call(`_gdalraster_g_is_valid`, geom)
}
#' @noRd
.g_is_empty <- function(geom) {
.Call(`_gdalraster_g_is_empty`, geom)
}
#' @noRd
.g_name <- function(geom) {
.Call(`_gdalraster_g_name`, geom)
}
#' @noRd
.g_intersects <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_intersects`, this_geom, other_geom)
}
#' @noRd
.g_equals <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_equals`, this_geom, other_geom)
}
#' @noRd
.g_disjoint <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_disjoint`, this_geom, other_geom)
}
#' @noRd
.g_touches <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_touches`, this_geom, other_geom)
}
#' @noRd
.g_contains <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_contains`, this_geom, other_geom)
}
#' @noRd
.g_within <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_within`, this_geom, other_geom)
}
#' @noRd
.g_crosses <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_crosses`, this_geom, other_geom)
}
#' @noRd
.g_overlaps <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_overlaps`, this_geom, other_geom)
}
#' @noRd
.g_buffer <- function(geom, dist, quad_segs = 30L) {
.Call(`_gdalraster_g_buffer`, geom, dist, quad_segs)
}
#' @noRd
.g_intersection <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_intersection`, this_geom, other_geom)
}
#' @noRd
.g_union <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_union`, this_geom, other_geom)
}
#' @noRd
.g_difference <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_difference`, this_geom, other_geom)
}
#' @noRd
.g_sym_difference <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_sym_difference`, this_geom, other_geom)
}
#' @noRd
.g_distance <- function(this_geom, other_geom) {
.Call(`_gdalraster_g_distance`, this_geom, other_geom)
}
#' @noRd
.g_length <- function(geom) {
.Call(`_gdalraster_g_length`, geom)
}
#' @noRd
.g_area <- function(geom) {
.Call(`_gdalraster_g_area`, geom)
}
#' @noRd
.g_centroid <- function(geom) {
.Call(`_gdalraster_g_centroid`, geom)
}
#' @noRd
.g_transform <- function(geom, srs_from, srs_to, wrap_date_line = FALSE, date_line_offset = 10L) {
.Call(`_gdalraster_g_transform`, geom, srs_from, srs_to, wrap_date_line, date_line_offset)
}
#' Does vector dataset exist
#'
#' @noRd
.ogr_ds_exists <- function(dsn, with_update = FALSE) {
.Call(`_gdalraster_ogr_ds_exists`, dsn, with_update)
}
#' Get the format driver short name for a vector dataset
#'
#' @noRd
.ogr_ds_format <- function(dsn) {
.Call(`_gdalraster_ogr_ds_format`, dsn)
}
#' Test if capabilities are available for a vector dataset
#'
#' @noRd
.ogr_ds_test_cap <- function(dsn, with_update = TRUE) {
.Call(`_gdalraster_ogr_ds_test_cap`, dsn, with_update)
}
#' Create a vector dataset. Optionally create a layer in the dataset.
#' A field is also created optionally (name and type only).
#'
#' @noRd
.create_ogr <- function(format, dst_filename, xsize, ysize, nbands, dataType, layer, geom_type, srs = "", fld_name = "", fld_type = "OFTInteger", dsco = NULL, lco = NULL, layer_defn = NULL) {
.Call(`_gdalraster_create_ogr`, format, dst_filename, xsize, ysize, nbands, dataType, layer, geom_type, srs, fld_name, fld_type, dsco, lco, layer_defn)
}
#' Get number of layers in a dataset
#'
#' @noRd
.ogr_ds_layer_count <- function(dsn) {
.Call(`_gdalraster_ogr_ds_layer_count`, dsn)
}
#' Get names of layers in a dataset
#'
#' @noRd
.ogr_ds_layer_names <- function(dsn) {
.Call(`_gdalraster_ogr_ds_layer_names`, dsn)
}
#' Does layer exist
#'
#' @noRd
.ogr_layer_exists <- function(dsn, layer) {
.Call(`_gdalraster_ogr_layer_exists`, dsn, layer)
}
#' Test if capabilities are available for a vector layer
#'
#' @noRd
.ogr_layer_test_cap <- function(dsn, layer, with_update = TRUE) {
.Call(`_gdalraster_ogr_layer_test_cap`, dsn, layer, with_update)
}
#' Create a layer in a vector dataset
#'
#' @noRd
.ogr_layer_create <- function(dsn, layer, layer_defn = NULL, geom_type = "UNKNOWN", srs = "", options = NULL) {
.Call(`_gdalraster_ogr_layer_create`, dsn, layer, layer_defn, geom_type, srs, options)
}
#' Delete a layer in a vector dataset
#'
#' @noRd
.ogr_layer_delete <- function(dsn, layer) {
.Call(`_gdalraster_ogr_layer_delete`, dsn, layer)
}
#' Get names of fields on a layer
#'
#' @noRd
.ogr_layer_field_names <- function(dsn, layer) {
.Call(`_gdalraster_ogr_layer_field_names`, dsn, layer)
}
#' Get field index or -1 if fld_name not found
#'
#' @noRd
.ogr_field_index <- function(dsn, layer, fld_name) {
.Call(`_gdalraster_ogr_field_index`, dsn, layer, fld_name)
}
#' Create a new field on layer
#'
#' @noRd
.ogr_field_create <- function(dsn, layer, fld_name, fld_type, fld_subtype = "OFSTNone", fld_width = 0L, fld_precision = 0L, is_nullable = TRUE, is_ignored = FALSE, is_unique = FALSE, default_value = "") {
.Call(`_gdalraster_ogr_field_create`, dsn, layer, fld_name, fld_type, fld_subtype, fld_width, fld_precision, is_nullable, is_ignored, is_unique, default_value)
}
#' Create a new geom field on layer
#'
#' @noRd
.ogr_geom_field_create <- function(dsn, layer, fld_name, geom_type, srs = "", is_nullable = TRUE, is_ignored = FALSE) {
.Call(`_gdalraster_ogr_geom_field_create`, dsn, layer, fld_name, geom_type, srs, is_nullable, is_ignored)
}
#' Rename an attribute field on a vector layer
#'
#' @noRd
.ogr_field_rename <- function(dsn, layer, fld_name, new_name) {
.Call(`_gdalraster_ogr_field_rename`, dsn, layer, fld_name, new_name)
}
#' Delete an attribute field on a vector layer
#'
#' @noRd
.ogr_field_delete <- function(dsn, layer, fld_name) {
.Call(`_gdalraster_ogr_field_delete`, dsn, layer, fld_name)
}
#' Execute an SQL statement against the data store
#'
#' @noRd
.ogr_execute_sql <- function(dsn, sql, spatial_filter = "", dialect = "") {
invisible(.Call(`_gdalraster_ogr_execute_sql`, dsn, sql, spatial_filter, dialect))
}
#' get PROJ version
#' @noRd
.getPROJVersion <- function() {
.Call(`_gdalraster_getPROJVersion`)
}
#' get search path(s) for PROJ resource files
#' @noRd
.getPROJSearchPaths <- function() {
.Call(`_gdalraster_getPROJSearchPaths`)
}
#' set search path(s) for PROJ resource files
#' @noRd
.setPROJSearchPaths <- function(paths) {
invisible(.Call(`_gdalraster_setPROJSearchPaths`, paths))
}
#' get whether PROJ networking capabilities are enabled
#' returns logical NA if GDAL < 3.4
#' @noRd
.getPROJEnableNetwork <- function() {
.Call(`_gdalraster_getPROJEnableNetwork`)
}
#' enable or disable PROJ networking capabilities
#' @noRd
.setPROJEnableNetwork <- function(enabled) {
invisible(.Call(`_gdalraster_setPROJEnableNetwork`, enabled))
}
#' Inverse project geospatial x/y coordinates to longitude/latitude
#'
#' `inv_project()` transforms geospatial x/y coordinates to
#' longitude/latitude in the same geographic coordinate system used by the
#' given projected spatial reference system. The output long/lat can
#' optionally be set to a specific geographic coordinate system by specifying
#' a well known name (see Details).
#'
#' @details
#' By default, the geographic coordinate system of the projection specified
#' by `srs` will be used. If a specific geographic coordinate system is
#' desired, then `well_known_gcs` can be set to one of the values below:
#' \tabular{rl}{
#' EPSG:n \tab where n is the code of a geographic coordinate system\cr
#' WGS84 \tab same as EPSG:4326\cr
#' WGS72 \tab same as EPSG:4322\cr
#' NAD83 \tab same as EPSG:4269\cr
#' NAD27 \tab same as EPSG:4267\cr
#' CRS84 \tab same as WGS84\cr
#' CRS72 \tab same as WGS72\cr
#' CRS27 \tab same as NAD27
#' }
#' The returned array will always be in longitude, latitude order
#' (traditional GIS order) regardless of the axis order defined for the
#' names above.
#'
#' @param pts A two-column data frame or numeric matrix containing geospatial
#' x/y coordinates.
#' @param srs Character string specifying the projected spatial reference
#' system for `pts`. May be in WKT format or any of the formats supported by
#' [srs_to_wkt()].
#' @param well_known_gcs Optional character string containing a supported
#' well known name of a geographic coordinate system (see Details for
#' supported values).
#' @returns Numeric array of longitude, latitude. An error is raised if the
#' transformation cannot be performed.
#' @seealso
#' [transform_xy()]
#' @examples
#' pt_file <- system.file("extdata/storml_pts.csv", package="gdalraster")
#' ## id, x, y in NAD83 / UTM zone 12N
#' pts <- read.csv(pt_file)
#' print(pts)
#' inv_project(pts[,-1], "EPSG:26912")
inv_project <- function(pts, srs, well_known_gcs = "") {
.Call(`_gdalraster_inv_project`, pts, srs, well_known_gcs)
}
#' Transform geospatial x/y coordinates
#'
#' `transform_xy()` transforms geospatial x/y coordinates to a new projection.
#'
#' @param pts A two-column data frame or numeric matrix containing geospatial
#' x/y coordinates.
#' @param srs_from Character string specifying the spatial reference system
#' for `pts`. May be in WKT format or any of the formats supported by
#' [srs_to_wkt()].
#' @param srs_to Character string specifying the output spatial reference
#' system. May be in WKT format or any of the formats supported by
#' [srs_to_wkt()].
#' @returns Numeric array of geospatial x/y coordinates in the projection
#' specified by `srs_to`.
#'
#' @seealso
#' [epsg_to_wkt()], [srs_to_wkt()], [inv_project()]
#' @examples
#' pt_file <- system.file("extdata/storml_pts.csv", package="gdalraster")
#' pts <- read.csv(pt_file)
#' print(pts)
#' ## id, x, y in NAD83 / UTM zone 12N
#' ## transform to NAD83 / CONUS Albers
#' transform_xy(pts = pts[, -1], srs_from = "EPSG:26912", srs_to = "EPSG:5070")
transform_xy <- function(pts, srs_from, srs_to) {
.Call(`_gdalraster_transform_xy`, pts, srs_from, srs_to)
}
#' Convert spatial reference from EPSG code to OGC Well Known Text
#'
#' `epsg_to_wkt()` exports the spatial reference for an EPSG code to
#' WKT format.
#'
#' @details
#' As of GDAL 3.0, the default format for WKT export is OGC WKT 1.
#' The WKT version can be overridden by using the OSR_WKT_FORMAT
#' configuration option (see [set_config_option()]).
#' Valid values are one of: SFSQL, WKT1_SIMPLE, WKT1, WKT1_GDAL,
#' WKT1_ESRI, WKT2_2015, WKT2_2018, WKT2, DEFAULT.
#' If SFSQL, a WKT1 string without AXIS, TOWGS84, AUTHORITY or
#' EXTENSION node is returned. If WKT1_SIMPLE, a WKT1 string without
#' AXIS, AUTHORITY or EXTENSION node is returned. WKT1 is an alias of
#' WKT1_GDAL. WKT2 will default to the latest revision implemented
#' (currently WKT2_2018). WKT2_2019 can be used as an alias of
#' WKT2_2018 since GDAL 3.2
#'
#' @param epsg Integer EPSG code.
#' @param pretty Logical. `TRUE` to return a nicely formatted WKT string
#' for display to a person. `FALSE` for a regular WKT string (the default).
#' @return Character string containing OGC WKT.
#'
#' @seealso
#' [srs_to_wkt()]
#'
#' @examples
#' epsg_to_wkt(5070)
#' writeLines(epsg_to_wkt(5070, pretty=TRUE))
#' set_config_option("OSR_WKT_FORMAT", "WKT2")
#' writeLines(epsg_to_wkt(5070, pretty=TRUE))
#' set_config_option("OSR_WKT_FORMAT", "")
epsg_to_wkt <- function(epsg, pretty = FALSE) {
.Call(`_gdalraster_epsg_to_wkt`, epsg, pretty)
}
#' Convert various spatial reference formats to Well Known Text
#'
#' `srs_to_wkt()` converts a spatial reference system (SRS) definition
#' in various text formats to WKT. The function will examine the input SRS,
#' try to deduce the format, and then export it to WKT.
#'
#' @details
#' This is a wrapper for `OSRSetFromUserInput()` in the GDAL Spatial
#' Reference System C API with output to WKT.
#' The input SRS may take the following forms:
#' * WKT - to convert WKT versions (see below)
#' * EPSG:n - EPSG code n
#' * AUTO:proj_id,unit_id,lon0,lat0 - WMS auto projections
#' * urn:ogc:def:crs:EPSG::n - OGC URNs
#' * PROJ.4 definitions
#' * filename - file to read for WKT, XML or PROJ.4 definition
#' * well known name such as NAD27, NAD83, WGS84 or WGS72
#' * IGNF:xxxx, ESRI:xxxx - definitions from the PROJ database
#' * PROJJSON (PROJ >= 6.2)
#'
#' This function is intended to be flexible, but by its nature it is
#' imprecise as it must guess information about the format intended.
#' [epsg_to_wkt()] could be used instead for EPSG codes.
#'
#' As of GDAL 3.0, the default format for WKT export is OGC WKT 1.
#' The WKT version can be overridden by using the OSR_WKT_FORMAT
#' configuration option (see [set_config_option()]).
#' Valid values are one of: SFSQL, WKT1_SIMPLE, WKT1, WKT1_GDAL,
#' WKT1_ESRI, WKT2_2015, WKT2_2018, WKT2, DEFAULT.
#' If SFSQL, a WKT1 string without AXIS, TOWGS84, AUTHORITY or
#' EXTENSION node is returned. If WKT1_SIMPLE, a WKT1 string without
#' AXIS, AUTHORITY or EXTENSION node is returned. WKT1 is an alias of
#' WKT1_GDAL. WKT2 will default to the latest revision implemented
#' (currently WKT2_2018). WKT2_2019 can be used as an alias of
#' WKT2_2018 since GDAL 3.2
#'
#' @param srs Character string containing an SRS definition in various
#' formats (see Details).
#' @param pretty Logical. `TRUE` to return a nicely formatted WKT string
#' for display to a person. `FALSE` for a regular WKT string (the default).
#' @return Character string containing OGC WKT.
#'
#' @seealso
#' [epsg_to_wkt()]
#'
#' @examples
#' srs_to_wkt("NAD83")
#' writeLines(srs_to_wkt("NAD83", pretty=TRUE))
#' set_config_option("OSR_WKT_FORMAT", "WKT2")
#' writeLines(srs_to_wkt("NAD83", pretty=TRUE))
#' set_config_option("OSR_WKT_FORMAT", "")
srs_to_wkt <- function(srs, pretty = FALSE) {
.Call(`_gdalraster_srs_to_wkt`, srs, pretty)
}
#' Check if WKT definition is a geographic coordinate system
#'
#' `srs_is_geographic()` will attempt to import the given WKT string as a
#' spatial reference system, and returns `TRUE` if the root is a
#' GEOGCS node. This is a wrapper for `OSRIsGeographic()` in the GDAL Spatial
#' Reference System C API.
#'
#' @param srs Character OGC WKT string for a spatial reference system
#' @return Logical. `TRUE` if `srs` is geographic, otherwise `FALSE`
#'
#' @seealso
#' [srs_is_projected()], [srs_is_same()]
#'
#' @examples
#' srs_is_geographic(epsg_to_wkt(5070))
#' srs_is_geographic(srs_to_wkt("WGS84"))
srs_is_geographic <- function(srs) {
.Call(`_gdalraster_srs_is_geographic`, srs)
}
#' Check if WKT definition is a projected coordinate system
#'
#' `srs_is_projected()` will attempt to import the given WKT string as a
#' spatial reference system (SRS), and returns `TRUE` if the SRS contains a
#' PROJCS node indicating a it is a projected coordinate system. This is a
#' wrapper for `OSRIsProjected()` in the GDAL Spatial Reference System C API.
#'
#' @param srs Character OGC WKT string for a spatial reference system
#' @return Logical. `TRUE` if `srs` is projected, otherwise `FALSE`
#'
#' @seealso
#' [srs_is_geographic()], [srs_is_same()]
#'
#' @examples
#' srs_is_projected(epsg_to_wkt(5070))
#' srs_is_projected(srs_to_wkt("WGS84"))
srs_is_projected <- function(srs) {
.Call(`_gdalraster_srs_is_projected`, srs)
}
#' Do these two spatial references describe the same system?
#'
#' `srs_is_same()` returns `TRUE` if these two spatial references describe
#' the same system. This is a wrapper for `OSRIsSame()` in the GDAL Spatial
#' Reference System C API.
#'
#' @param srs1 Character string. OGC WKT for a spatial reference system.
#' @param srs2 Character string. OGC WKT for a spatial reference system.
#' @param criterion Character string. One of `STRICT`, `EQUIVALENT`,
#' `EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS`.
#' Defaults to `EQUIVALENT_EXCEPT_AXIS_ORDER_GEOGCRS`.
#' @param ignore_axis_mapping Logical scalar. If `TRUE`, sets
#' `IGNORE_DATA_AXIS_TO_SRS_AXIS_MAPPING=YES` in the call to `OSRIsSameEx()`
#' in the GDAL Spatial Reference System API. Defaults to `NO`.
#' @param ignore_coord_epoch Logical scalar. If `TRUE`, sets
#' `IGNORE_COORDINATE_EPOCH=YES` in the call to `OSRIsSameEx()`
#' in the GDAL Spatial Reference System API. Defaults to `NO`.
#' @return Logical. `TRUE` if these two spatial references describe the same
#' system, otherwise `FALSE`.
#'
#' @seealso
#' [srs_is_geographic()], [srs_is_projected()]
#'
#' @examples
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' ds <- new(GDALRaster, elev_file, TRUE)
#' srs_is_same(ds$getProjectionRef(), epsg_to_wkt(26912))
#' srs_is_same(ds$getProjectionRef(), epsg_to_wkt(5070))
#' ds$close()
srs_is_same <- function(srs1, srs2, criterion = "", ignore_axis_mapping = FALSE, ignore_coord_epoch = FALSE) {
.Call(`_gdalraster_srs_is_same`, srs1, srs2, criterion, ignore_axis_mapping, ignore_coord_epoch)
}
#' Get the bounding box of a geometry specified in OGC WKT format
#'
#' `bbox_from_wkt()` returns the bounding box of a WKT 2D geometry
#' (e.g., LINE, POLYGON, MULTIPOLYGON).
#'
#' @param wkt Character. OGC WKT string for a simple feature 2D geometry.
#' @param extend_x Numeric scalar. Distance to extend the output bounding box
#' in both directions along the x-axis
#' (results in `xmin = bbox[1] - extend_x`, `xmax = bbox[3] + extend_x`).
#' @param extend_y Numeric scalar. Distance to extend the output bounding box
#' in both directions along the y-axis
#' (results in `ymin = bbox[2] - extend_y`, `ymax = bbox[4] + extend_y`).
#' @return Numeric vector of length four containing the xmin, ymin,
#' xmax, ymax of the geometry specified by `wkt` (possibly extended by values
#' in `extend_x`, `extend_y`).
#'
#' @seealso
#' [bbox_to_wkt()]
#'
#' @examples
#' bnd <- "POLYGON ((324467.3 5104814.2, 323909.4 5104365.4, 323794.2
#' 5103455.8, 324970.7 5102885.8, 326420.0 5103595.3, 326389.6 5104747.5,
#' 325298.1 5104929.4, 325298.1 5104929.4, 324467.3 5104814.2))"
#' bbox_from_wkt(bnd, 100, 100)
bbox_from_wkt <- function(wkt, extend_x = 0, extend_y = 0) {
.Call(`_gdalraster_bbox_from_wkt`, wkt, extend_x, extend_y)
}
#' Convert a bounding box to POLYGON in OGC WKT format
#'
#' `bbox_to_wkt()` returns a WKT POLYGON string for the given bounding box.
#' Requires GDAL built with the GEOS library.
#'
#' @param bbox Numeric vector of length four containing xmin, ymin,
#' xmax, ymax.
#' @param extend_x Numeric scalar. Distance in units of `bbox` to extend the
#' rectangle in both directions along the x-axis
#' (results in `xmin = bbox[1] - extend_x`, `xmax = bbox[3] + extend_x`).
#' @param extend_y Numeric scalar. Distance in units of `bbox` to extend the
#' rectangle in both directions along the y-axis
#' (results in `ymin = bbox[2] - extend_y`, `ymax = bbox[4] + extend_y`).
#' @return Character string for an OGC WKT polygon.
#' `NA` is returned if GDAL was built without the GEOS library.
#'
#' @seealso
#' [bbox_from_wkt()], [g_buffer()]
#'
#' @examples
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' ds <- new(GDALRaster, elev_file, read_only=TRUE)
#' bbox_to_wkt(ds$bbox())
#' ds$close()
bbox_to_wkt <- function(bbox, extend_x = 0, extend_y = 0) {
.Call(`_gdalraster_bbox_to_wkt`, bbox, extend_x, extend_y)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.