Nothing
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#' Helper functions for GDAL raster data types
#'
#' These are convenience functions that return information about a raster
#' data type, return the smallest data type that can fully express two input
#' data types, or find the smallest data type able to support specified
#' requirements.
#'
#' @name data_type_helpers
#'
#' @details
#' `dt_size()` returns the data type size in bytes by default, optionally in
#' bits (returns zero if `dt` is not recognized).
#'
#' `dt_is_complex()` returns `TRUE` if the passed type is complex (one of
#' CInt16, CInt32, CFloat32 or CFloat64), i.e., if it consists of a real and
#' imaginary component.
#'
#' `dt_is_integer()` returns `TRUE` if the passed type is integer (one of
#' Byte, Int16, UInt16, Int32, UInt32, CInt16, CInt32).
#'
#' `dt_is_floating()` returns `TRUE` if the passed type is floating (one of
#' Float32, Float16, Float64, CFloat16, CFloat32, CFloat64).
#'
#' `dt_is_signed()` returns `TRUE` if the passed type is signed.
#'
#' `dt_union()` returns the smallest data type that can fully express both
#' input data types (returns a data type name as character string).
#'
#' `dt_union_with_value()` unions a data type with the data type found for a
#' given value, and returns the resulting data type name as character string.
#'
#' `dt_find()` finds the smallest data type able to support the given
#' requirements (returns a data type name as character string).
#'
#' `dt_find_for_value()` finds the smallest data type able to support the
#' given `value` (returns a data type name as character string).
#'
#' @param dt Character string containing a GDAL data type name (e.g.,
#' `"Byte"`, `"Int16"`, `"UInt16"`, `"Int32"`, `"UInt32"`, `"Float32"`,
#' `"Float64"`, etc.)
#' @param as_bytes Logical value, `TRUE` to return data type size in bytes
#' (the default), `FALSE` to return the size in bits.
#' @param dt_other Character string containing a GDAL data type name.
#' @param value Numeric value for which to find a data type (passing the real
#' part if `is_complex = TRUE`).
#' @param is_complex Logical value, `TRUE` if `value` is complex (default is
#' `FALSE`), or if complex values are necessary in `dt_find()`.
#' @param bits Integer value specifying the number of bits necessary.
#' @param is_signed Logical value, `TRUE` if negative values are necessary.
#' @param is_floating Logical value, `TRUE` if non-integer values are
#' necessary.
#'
#' @seealso
#' [`GDALRaster$getDataTypeName()`][GDALRaster]
#'
#' @examples
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' ds <- new(GDALRaster, elev_file)
#'
#' ds$getDataTypeName(band = 1) |> dt_size()
#' ds$getDataTypeName(band = 1) |> dt_size(as_bytes = FALSE)
#' ds$getDataTypeName(band = 1) |> dt_is_complex()
#' ds$getDataTypeName(band = 1) |> dt_is_integer()
#' ds$getDataTypeName(band = 1) |> dt_is_floating()
#' ds$getDataTypeName(band = 1) |> dt_is_signed()
#'
#' ds$close()
#'
#' f <- system.file("extdata/complex.tif", package="gdalraster")
#' ds <- new(GDALRaster, f)
#'
#' ds$getDataTypeName(band = 1) |> dt_size()
#' ds$getDataTypeName(band = 1) |> dt_size(as_bytes = FALSE)
#' ds$getDataTypeName(band = 1) |> dt_is_complex()
#' ds$getDataTypeName(band = 1) |> dt_is_integer()
#' ds$getDataTypeName(band = 1) |> dt_is_floating()
#' ds$getDataTypeName(band = 1) |> dt_is_signed()
#'
#' ds$close()
#'
#' dt_union("Byte", "Int16")
#' dt_union_with_value("Byte", -1)
#' dt_union_with_value("Byte", 256)
#'
#' dt_find(bits = 32, is_signed = FALSE, is_floating = FALSE)
#' dt_find_for_value(0)
#' dt_find_for_value(-1)
#' dt_find_for_value(NaN)
#' dt_find_for_value(.Machine$integer.max)
dt_size <- function(dt, as_bytes = TRUE) {
.Call(`_gdalraster_dt_size`, dt, as_bytes)
}
#' @rdname data_type_helpers
dt_is_complex <- function(dt) {
.Call(`_gdalraster_dt_is_complex`, dt)
}
#' @rdname data_type_helpers
dt_is_integer <- function(dt) {
.Call(`_gdalraster_dt_is_integer`, dt)
}
#' @rdname data_type_helpers
dt_is_floating <- function(dt) {
.Call(`_gdalraster_dt_is_floating`, dt)
}
#' @rdname data_type_helpers
dt_is_signed <- function(dt) {
.Call(`_gdalraster_dt_is_signed`, dt)
}
#' @rdname data_type_helpers
dt_union <- function(dt, dt_other) {
.Call(`_gdalraster_dt_union`, dt, dt_other)
}
#' @rdname data_type_helpers
dt_union_with_value <- function(dt, value, is_complex = FALSE) {
.Call(`_gdalraster_dt_union_with_value`, dt, value, is_complex)
}
#' @rdname data_type_helpers
dt_find <- function(bits, is_signed, is_floating, is_complex = FALSE) {
.Call(`_gdalraster_dt_find`, bits, is_signed, is_floating, is_complex)
}
#' @rdname data_type_helpers
dt_find_for_value <- function(value, is_complex = FALSE) {
.Call(`_gdalraster_dt_find_for_value`, value, is_complex)
}
#' Get GDAL version
#'
#' `gdal_version()` returns a character vector of GDAL runtime version
#' information. `gdal_version_num()` returns only the full version number
#' (`gdal_version()[2]`) as an integer value.
#'
#' @name gdal_version
#'
#' @returns
#' `gdal_version()` returns a 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”
#'
#' `gdal_version_num()` returns `as.integer(gdal_version()[2])`
#' @examples
#' gdal_version()
#'
#' gdal_version_num()
gdal_version <- function() {
.Call(`_gdalraster_gdal_version`)
}
#' @rdname gdal_version
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 maximum memory size available for the GDAL block cache
#'
#' `get_cache_max()` returns the maximum amount of memory available to the
#' GDALRasterBlock caching system for caching raster read/write data. Wrapper
#' of `GDALGetCacheMax64()` with return value in MB by default.
#'
#' @details
#' The first time this function is called, it will read the `GDAL_CACHEMAX`
#' configuration option to initialize the maximum cache memory. The value of
#' the configuration option can be expressed as x% of the usable physical RAM
#' (which may potentially be used by other processes). Otherwise it is
#' expected to be a value in MB.
#' As of GDAL 3.10, the default value, if `GDAL_CACHEMAX` has not been set
#' explicitly, is 5% of usable physical RAM.
#'
#' @param units Character string specifying units for the return value. One of
#' `"MB"` (the default), `"GB"`, `"KB"` or `"bytes"` (values of `"byte"`,
#' `"B"` and empty string `""` are also recognized to mean bytes).
#' @returns A numeric value carrying the `integer64` class attribute. Maximum
#' cache memory available in the requested units.
#'
#' @note
#' The value of the `GDAL_CACHEMAX` configuration option is only consulted the
#' first time the cache size is requested (i.e., it must be set as a
#' configuration option prior to any raster I/O during the current session).
#' To change this value programmatically during operation of the program it is
#' better to use [set_cache_max()] (in which case, always given in bytes).
#'
#' @seealso
#' [GDAL_CACHEMAX configuration option](https://gdal.org/en/stable/user/configoptions.html#performance-and-caching)
#'
#' [get_config_option()], [set_config_option()], [get_usable_physical_ram()],
#' [get_cache_used()], [set_cache_max()]
#'
#' @examples
#' get_cache_max()
get_cache_max <- function(units = "MB") {
.Call(`_gdalraster_get_cache_max`, units)
}
#' 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. Wrapper of `GDALGetCacheUsed64()` with return
#' value in MB by default.
#'
#' @param units Character string specifying units for the return value. One of
#' `"MB"` (the default), `"GB"`, `"KB"` or `"bytes"` (values of `"byte"`,
#' `"B"` and empty string `""` are also recognized to mean bytes).
#' @returns A numeric value carrying the `integer64` class attribute. Amount
#' of the available cache memory currently in use in the requested units.
#'
#' @seealso
#' [GDAL Block Cache](https://usdaforestservice.github.io/gdalraster/articles/gdal-block-cache.html)
#'
#' [get_cache_max()], [set_cache_max()]
#'
#' @examples
#' get_cache_used()
get_cache_used <- function(units = "MB") {
.Call(`_gdalraster_get_cache_used`, units)
}
#' Set the maximum memory size for the GDAL block cache
#'
#' `set_cache_max()` sets the maximum amount of memory that GDAL is permitted
#' to use for GDALRasterBlock caching.
#' *The unit of the value to set is bytes.* Wrapper of `GDALSetCacheMax64()`.
#'
#' @param nbytes A numeric value optionally carrying the `integer64` class
#' attribute (assumed to be a whole number, will be coerced to integer by
#' truncation). Specifies the new cache size in bytes (maximum number of bytes
#' for caching).
#' @returns No return value, called for side effects.
#'
#' @note
#' **This function will not make any attempt to check the consistency of the
#' passed value with the effective capabilities of the OS.**
#'
#' It is recommended to consult the documentation for `get_cache_max()` and
#' `get_cache_used()` before using this function.
#'
#' [get_cache_max()], [get_cache_used()]
#'
#' @examples
#' (cachemax <- get_cache_max("bytes"))
#'
#' set_cache_max(1e8)
#' get_cache_max() # returns in MB by default
#'
#' # reset to original
#' set_cache_max(cachemax)
#' get_cache_max()
set_cache_max <- function(nbytes) {
invisible(.Call(`_gdalraster_set_cache_max`, nbytes))
}
#' @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_get_filename <- function(full_filename) {
.Call(`_gdalraster_cpl_get_filename`, full_filename)
}
#' @noRd
.cpl_get_basename <- function(full_filename) {
.Call(`_gdalraster_cpl_get_basename`, full_filename)
}
#' @noRd
.cpl_get_extension <- function(full_filename) {
.Call(`_gdalraster_cpl_get_extension`, full_filename)
}
#' @noRd
.cpl_http_cleanup <- function() {
invisible(.Call(`_gdalraster_cpl_http_cleanup`))
}
#' 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)
}
#' Returns bbox geospatial x,y coordinates (xmin, ymin, xmax, ymax) from
#' inputs of geotransform vector and the grid pixel/line extent
#' @noRd
.bbox_grid_to_geo <- function(gt, grid_xmin, grid_xmax, grid_ymin, grid_ymax) {
.Call(`_gdalraster_bbox_grid_to_geo_`, gt, grid_xmin, grid_xmax, grid_ymin, grid_ymax)
}
#' Flip raster data vertically
#' @noRd
.flip_vertical <- function(v, xsize, ysize, nbands) {
.Call(`_gdalraster_flip_vertical`, v, xsize, ysize, nbands)
}
#' 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()
#' \dontshow{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, options, quiet) {
.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),]
#' \dontshow{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 (gdal_version_num() >= gdal_compute_version(3, 8, 0)) {
#' # command-line arguments for gdal_footprint
#' args <- c("-t_srs", "EPSG:4326")
#' footprint(evt_file, out_file, args)
#' \dontshow{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
#' ynp_shp <- file.path(tempdir(), "ynp_fires.shp")
#' ogr2ogr(src, ynp_shp, src_layers = "mtbs_perims")
#'
#' # Reproject to WGS84
#' ynp_gpkg <- file.path(tempdir(), "ynp_fires.gpkg")
#' args <- c("-t_srs", "EPSG:4326", "-nln", "fires_wgs84")
#' ogr2ogr(src, ynp_gpkg, 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>"
#' # Using -update mode to write a new layer in the existing DSN
#' bb <- c(469685.97, 11442.45, 544069.63, 85508.15)
#' args <- c("-update", "-nln", "fires_clip", "-spat", bb)
#' ogr2ogr(src, ynp_gpkg, cl_arg = args)
#'
#' # Filter features by a -where clause
#' sql <- "ig_year >= 2000 ORDER BY ig_year"
#' args <- c("-update", "-nln", "fires_2000-2020", "-where", sql)
#' ogr2ogr(src, ynp_gpkg, src_layers = "mtbs_perims", cl_arg = args)
#'
#' # Dissolve features based on a shared attribute value
#' if (has_spatialite()) {
#' sql <- "SELECT ig_year, ST_Union(geom) AS geom FROM mtbs_perims GROUP BY ig_year"
#' args <- c("-update", "-sql", sql, "-dialect", "SQLITE")
#' args <- c(args, "-nlt", "MULTIPOLYGON", "-nln", "dissolved_on_year")
#' ogr2ogr(src, ynp_gpkg, cl_arg = args)
#' }
#' \dontshow{deleteDataset(ynp_shp)}
#' \dontshow{deleteDataset(ynp_gpkg)}
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()], [ogr_manage]
#'
#' @examplesIf gdal_version_num() >= gdal_compute_version(3, 7, 0)
#' src <- system.file("extdata/ynp_fires_1984_2022.gpkg", package="gdalraster")
#'
#' # Get the names of the layers in a GeoPackage file
#' ogrinfo(src)
#'
#' # Summary of a layer
#' ogrinfo(src, "mtbs_perims")
#'
#' # 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)
#'
#' # 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)
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, dst_dataset, cl_arg, quiet = FALSE) {
.Call(`_gdalraster_rasterize`, src_dsn, dst_filename, dst_dataset, 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)
#' \dontshow{deleteDataset(mask_file)}
#' \dontshow{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}).
#'
#' Called from and documented in R/gdal_util.R
#'
#' @noRd
.translate <- function(src_ds, dst_filename, cl_arg = NULL, quiet = FALSE) {
.Call(`_gdalraster_translate`, src_ds, 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}).
#'
#' Called from and documented in R/gdal_util.R
#'
#' Destination raster is specified here as either:
#' dst_filename - the destination dataset path or ""
#' dst_dataset - list of length 1 containg a GDALRaster object or empty list
#' (workaround for a nullable dataset argument)
#'
#' @noRd
.warp <- function(src_datasets, dst_filename, dst_dataset, t_srs, cl_arg, quiet) {
.Call(`_gdalraster_warp`, src_datasets, dst_filename, dst_dataset, 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()
#' \dontshow{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()
#' \dontshow{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)
}
#' Validate the list of creation options that are handled by a driver
#'
#' `validateCreationOptions()` is a helper function primarily used by GDAL's
#' Create() and CreateCopy() to validate that the passed-in list of creation
#' options is compatible with the GDAL_DMD_CREATIONOPTIONLIST metadata item
#' defined by some drivers. If the GDAL_DMD_CREATIONOPTIONLIST metadata item
#' is not defined, this function will return `TRUE`. Otherwise it will check
#' that the keys and values in the list of creation options are compatible
#' with the capabilities declared by the GDAL_DMD_CREATIONOPTIONLIST metadata
#' item. In case of incompatibility a message will be emitted and `FALSE` will
#' be returned. Wrapper of `GDALValidateCreationOptions()` in the GDAL API.
#'
#' @param format Character string giving a format driver short name
#' (e.g., `"GTiff"`).
#' @param options A character vector of format-specific creation options as
#' `"NAME=VALUE"` pairs.
#' @returns A logical value, `TRUE` if the given creation options are
#' compatible with the capabilities declared by the GDAL_DMD_CREATIONOPTIONLIST
#' metadata item for the specified format driver (or if the
#' GDAL_DMD_CREATIONOPTIONLIST metadata item is not defined for this driver),
#' otherwise `FALSE`.
#'
#' @seealso
#' [getCreationOptions()], [create()], [createCopy()]
#'
#' @examples
#' validateCreationOptions("GTiff", c("COMPRESS=LZW", "TILED=YES"))
validateCreationOptions <- function(format, options) {
.Call(`_gdalraster_validateCreationOptions`, format, options)
}
#' 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 (gdal_version_num() >= gdal_compute_version(3, 7, 0)) {
#' result <- vsi_copy_file(elev_file, tmp_file)
#' (result == 0)
#' 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
#' elev_file <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' mem_file <- file.path("/vsimem", "tmp.tif")
#' copyDatasetFiles(mem_file, elev_file)
#' vsi_read_dir("/vsimem")
#' vsi_unlink(mem_file)
#' vsi_read_dir("/vsimem")
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)
#'
#' # try to be CRAN-compliant for the example:
#' set_config_option("GDAL_HTTP_CONNECTTIMEOUT", "10")
#' set_config_option("GDAL_HTTP_TIMEOUT", "10")
#'
#' 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 (gdal_version_num() >= gdal_compute_version(3, 6, 0))
#' 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 (gdal_version_num() >= gdal_compute_version(3, 6, 0))
#' 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()]
#'
#' @examplesIf gdal_version_num() >= gdal_compute_version(3, 7, 0)
#' # validate an SOZip-enabled file
#' # Requires GDAL >= 3.7
#' f <- system.file("extdata/ynp_features.zip", package = "gdalraster")
#'
#' zf <- file.path("/vsizip", f)
#' # files in zip archive
#' vsi_read_dir(zf)
#'
#' # SOZip metadata for ynp_features.gpkg
#' zf_gpkg <- file.path(zf, "ynp_features.gpkg")
#' vsi_get_file_metadata(zf_gpkg, domain = "ZIP")
vsi_get_file_metadata <- function(filename, domain) {
.Call(`_gdalraster_vsi_get_file_metadata`, filename, domain)
}
#' Returns the actual URL of a supplied VSI filename
#'
#' `vsi_get_actual_url()` returns the actual URL of a supplied filename.
#' Currently only returns a non-NULL value for network-based virtual file
#' systems. For example "/vsis3/bucket/filename" will be expanded as
#' "https://bucket.s3.amazon.com/filename".
#' Wrapper for `VSIGetActualURL()` in the GDAL API.
#'
#' @param filename Character string containing a /vsiPREFIX/ filename.
#' @returns Character string containing the actual URL, or `NULL` if
#' `filename` is not a network-based virtual file system.
#'
#' @seealso
#' [vsi_get_signed_url()]
#'
#' @examples
#' \dontrun{
#' f <- "/vsiaz/items/io-lulc-9-class.parquet"
#' set_config_option("AZURE_STORAGE_ACCOUNT", "pcstacitems")
#' # token obtained from:
#' # https://planetarycomputer.microsoft.com/api/sas/v1/token/pcstacitems/items
#' set_config_option("AZURE_STORAGE_SAS_TOKEN","<token>")
#' vsi_get_actual_url(f)
#' #> [1] "https://pcstacitems.blob.core.windows.net/items/io-lulc-9-class.parquet"
#' vsi_get_signed_url(f)
#' #> [1] "https://pcstacitems.blob.core.windows.net/items/io-lulc-9-class.parquet?<token>"
#' }
vsi_get_actual_url <- function(filename) {
.Call(`_gdalraster_vsi_get_actual_url`, filename)
}
#' Returns a signed URL for a supplied VSI filename
#'
#' `vsi_get_signed_url()` Returns a signed URL of a supplied filename.
#' Currently only returns a non-NULL value for /vsis3/, /vsigs/, /vsiaz/ and
#' /vsioss/ For example "/vsis3/bucket/filename" will be expanded as
#' "https://bucket.s3.amazon.com/filename?X-Amz-Algorithm=AWS4-HMAC-SHA256..."
#' Configuration options that apply for file opening (typically to provide
#' credentials), and are returned by `vsi_get_fs_options()`, are also valid
#' in that context.
#' Wrapper for `VSIGetSignedURL()` in the GDAL API.
#'
#' @details
#' The `options` argument accepts a character vector of name=value pairs.
#' For /vsis3/, /vsigs/, /vsiaz/ and /vsioss/, the following options are
#' supported:
#' * `START_DATE=YYMMDDTHHMMSSZ`: date and time in UTC following ISO 8601
#' standard, corresponding to the start of validity of the URL. If not
#' specified, current date time.
#' * `EXPIRATION_DELAY=number_of_seconds`: number between 1 and 604800 (seven
#' days) for the validity of the signed URL. Defaults to 3600 (one hour).
#' * `VERB=GET/HEAD/DELETE/PUT/POST`: HTTP VERB for which the request will be
#' used. Defaults to `GET`.
#'
#' /vsiaz/ supports additional options:
#' * `SIGNEDIDENTIFIER=value`: to relate the given shared access signature to
#' a corresponding stored access policy.
#' * `SIGNEDPERMISSIONS=r|w`: permissions associated with the shared access
#' signature. Normally deduced from `VERB`.
#'
#' @param filename Character string containing a /vsiPREFIX/ filename.
#' @param options Character vector of `NAME=VALUE` pairs (see Details).
#' @returns Character string containing the signed URL, or `NULL` if
#' `filename` is not a network-based virtual file system.
#'
#' @seealso
#' [vsi_get_actual_url()]
#'
#' @examples
#' \dontrun{
#' f <- "/vsiaz/items/io-lulc-9-class.parquet"
#' set_config_option("AZURE_STORAGE_ACCOUNT", "pcstacitems")
#' # token obtained from:
#' # https://planetarycomputer.microsoft.com/api/sas/v1/token/pcstacitems/items
#' set_config_option("AZURE_STORAGE_SAS_TOKEN", "<token>")
#' vsi_get_actual_url(f)
#' #> [1] "https://pcstacitems.blob.core.windows.net/items/io-lulc-9-class.parquet"
#' vsi_get_signed_url(f)
#' #> [1] "https://pcstacitems.blob.core.windows.net/items/io-lulc-9-class.parquet?<token>"
#' }
vsi_get_signed_url <- function(filename, options = NULL) {
.Call(`_gdalraster_vsi_get_signed_url`, filename, options)
}
#' Returns if the file/filesystem is "local".
#'
#' `vsi_is_local()` returns whether the file/filesystem is "local".
#' Wrapper for `VSIIsLocal()` in the GDAL API. Requires GDAL >= 3.6.
#'
#' @param filename Character string. The path of the filesystem object to be
#' tested.
#' @returns Logical scalar. `TRUE` if if the input file path is local.
#'
#' @note
#' The concept of local is mostly by opposition with a network / remote file
#' system whose access time can be long.
#'
#' /vsimem/ is considered to be a local file system, although a
#' non-persistent one.
#'
#' @examples
#' # Requires GDAL >= 3.6
#' if (gdal_version_num() >= gdal_compute_version(3, 6, 0))
#' print(vsi_is_local("/vsimem/test-mem-file.tif"))
vsi_is_local <- function(filename) {
.Call(`_gdalraster_vsi_is_local`, filename)
}
#' @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_wkb2wkt <- function(geom, as_iso = FALSE) {
.Call(`_gdalraster_g_wkb2wkt`, geom, as_iso)
}
#' @noRd
.g_wkb_list2wkt <- function(geom, as_iso = FALSE) {
.Call(`_gdalraster_g_wkb_list2wkt`, geom, as_iso)
}
#' @noRd
.g_wkt2wkb <- function(geom, as_iso = FALSE, byte_order = "LSB") {
.Call(`_gdalraster_g_wkt2wkb`, geom, as_iso, byte_order)
}
#' @noRd
.g_wkt_vector2wkb <- function(geom, as_iso = FALSE, byte_order = "LSB") {
.Call(`_gdalraster_g_wkt_vector2wkb`, geom, as_iso, byte_order)
}
#' @noRd
.g_create <- function(geom_type, pts, as_iso = FALSE, byte_order = "LSB") {
.Call(`_gdalraster_g_create`, geom_type, pts, as_iso, byte_order)
}
#' @noRd
.g_add_geom <- function(sub_geom, container, as_iso = FALSE, byte_order = "LSB") {
.Call(`_gdalraster_g_add_geom`, sub_geom, container, as_iso, byte_order)
}
#' @noRd
.g_is_valid <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_is_valid`, geom, quiet)
}
#' @noRd
.g_make_valid <- function(geom, method = "LINEWORK", keep_collapsed = FALSE, as_iso = FALSE, byte_order = "LSB", quiet = FALSE) {
.Call(`_gdalraster_g_make_valid`, geom, method, keep_collapsed, as_iso, byte_order, quiet)
}
#' @noRd
.g_swap_xy <- function(geom, as_iso = FALSE, byte_order = "LSB", quiet = FALSE) {
.Call(`_gdalraster_g_swap_xy`, geom, as_iso, byte_order, quiet)
}
#' @noRd
.g_is_empty <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_is_empty`, geom, quiet)
}
#' @noRd
.g_is_3D <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_is_3D`, geom, quiet)
}
#' @noRd
.g_is_measured <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_is_measured`, geom, quiet)
}
#' @noRd
.g_name <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_name`, geom, quiet)
}
#' @noRd
.g_summary <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_summary`, geom, quiet)
}
#' @noRd
.g_envelope <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_envelope`, geom, quiet)
}
#' @noRd
.g_intersects <- function(this_geom, other_geom, quiet = FALSE) {
.Call(`_gdalraster_g_intersects`, this_geom, other_geom, quiet)
}
#' @noRd
.g_equals <- function(this_geom, other_geom, quiet = FALSE) {
.Call(`_gdalraster_g_equals`, this_geom, other_geom, quiet)
}
#' @noRd
.g_disjoint <- function(this_geom, other_geom, quiet = FALSE) {
.Call(`_gdalraster_g_disjoint`, this_geom, other_geom, quiet)
}
#' @noRd
.g_touches <- function(this_geom, other_geom, quiet = FALSE) {
.Call(`_gdalraster_g_touches`, this_geom, other_geom, quiet)
}
#' @noRd
.g_contains <- function(this_geom, other_geom, quiet = FALSE) {
.Call(`_gdalraster_g_contains`, this_geom, other_geom, quiet)
}
#' @noRd
.g_within <- function(this_geom, other_geom, quiet = FALSE) {
.Call(`_gdalraster_g_within`, this_geom, other_geom, quiet)
}
#' @noRd
.g_crosses <- function(this_geom, other_geom, quiet = FALSE) {
.Call(`_gdalraster_g_crosses`, this_geom, other_geom, quiet)
}
#' @noRd
.g_overlaps <- function(this_geom, other_geom, quiet = FALSE) {
.Call(`_gdalraster_g_overlaps`, this_geom, other_geom, quiet)
}
#' @noRd
.g_buffer <- function(geom, dist, quad_segs = 30L, as_iso = FALSE, byte_order = "LSB", quiet = FALSE) {
.Call(`_gdalraster_g_buffer`, geom, dist, quad_segs, as_iso, byte_order, quiet)
}
#' @noRd
.g_simplify <- function(geom, tolerance, preserve_topology = TRUE, as_iso = FALSE, byte_order = "LSB", quiet = FALSE) {
.Call(`_gdalraster_g_simplify`, geom, tolerance, preserve_topology, as_iso, byte_order, quiet)
}
#' @noRd
.g_intersection <- function(this_geom, other_geom, as_iso = FALSE, byte_order = "LSB", quiet = FALSE) {
.Call(`_gdalraster_g_intersection`, this_geom, other_geom, as_iso, byte_order, quiet)
}
#' @noRd
.g_union <- function(this_geom, other_geom, as_iso = FALSE, byte_order = "LSB", quiet = FALSE) {
.Call(`_gdalraster_g_union`, this_geom, other_geom, as_iso, byte_order, quiet)
}
#' @noRd
.g_difference <- function(this_geom, other_geom, as_iso = FALSE, byte_order = "LSB", quiet = FALSE) {
.Call(`_gdalraster_g_difference`, this_geom, other_geom, as_iso, byte_order, quiet)
}
#' @noRd
.g_sym_difference <- function(this_geom, other_geom, as_iso = FALSE, byte_order = "LSB", quiet = FALSE) {
.Call(`_gdalraster_g_sym_difference`, this_geom, other_geom, as_iso, byte_order, quiet)
}
#' @noRd
.g_distance <- function(this_geom, other_geom, quiet = FALSE) {
.Call(`_gdalraster_g_distance`, this_geom, other_geom, quiet)
}
#' @noRd
.g_length <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_length`, geom, quiet)
}
#' @noRd
.g_area <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_area`, geom, quiet)
}
#' @noRd
.g_geodesic_area <- function(geom, srs, traditional_gis_order = TRUE, quiet = FALSE) {
.Call(`_gdalraster_g_geodesic_area`, geom, srs, traditional_gis_order, quiet)
}
#' @noRd
.g_geodesic_length <- function(geom, srs, traditional_gis_order = TRUE, quiet = FALSE) {
.Call(`_gdalraster_g_geodesic_length`, geom, srs, traditional_gis_order, quiet)
}
#' @noRd
.g_centroid <- function(geom, quiet = FALSE) {
.Call(`_gdalraster_g_centroid`, geom, quiet)
}
#' @noRd
.g_transform <- function(geom, srs_from, srs_to, wrap_date_line = FALSE, date_line_offset = 10L, traditional_gis_order = TRUE, as_iso = FALSE, byte_order = "LSB", quiet = FALSE) {
.Call(`_gdalraster_g_transform`, geom, srs_from, srs_to, wrap_date_line, date_line_offset, traditional_gis_order, as_iso, byte_order, quiet)
}
#' 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.
#'
#' @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)
}
#' 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)
}
#' 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)
}
#' Rename a layer in a vector dataset
#'
#' @noRd
.ogr_layer_rename <- function(dsn, layer, new_name) {
.Call(`_gdalraster_ogr_layer_rename`, dsn, layer, new_name)
}
#' 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_unique = FALSE, default_value = "") {
.Call(`_gdalraster_ogr_field_create`, dsn, layer, fld_name, fld_type, fld_subtype, fld_width, fld_precision, is_nullable, 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) {
.Call(`_gdalraster_ogr_geom_field_create`, dsn, layer, fld_name, geom_type, srs, is_nullable)
}
#' 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))
}
#' Convert spatial reference definitions to OGC Well Known Text
#'
#' These functions convert various spatial reference formats to Well Known
#' Text (WKT).
#'
#' @name srs_convert
#'
#' @details
#' `epsg_to_wkt()` exports the spatial reference for an EPSG code to
#' WKT format.
#' Wrapper for `OSRImportFromEPSG()` in the GDAL Spatial Reference System API
#' with output to WKT.
#'
#' `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.
#' Wrapper for `OSRSetFromUserInput()` in the GDAL Spatial Reference System
#' 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)
#'
#' `srs_to_wkt()` 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 epsg Integer EPSG code.
#' @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
#' [srs_query]
#'
#' @examples
#' epsg_to_wkt(5070)
#' writeLines(epsg_to_wkt(5070, pretty=TRUE))
#'
#' 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", "")
epsg_to_wkt <- function(epsg, pretty = FALSE) {
.Call(`_gdalraster_epsg_to_wkt`, epsg, pretty)
}
#' @rdname srs_convert
srs_to_wkt <- function(srs, pretty = FALSE) {
.Call(`_gdalraster_srs_to_wkt`, srs, pretty)
}
#' Obtain information about a spatial reference system
#'
#' Bindings to a subset of the GDAL Spatial Reference System API
#' (\url{https://gdal.org/en/stable/api/ogr_srs_api.html}).
#' These functions return various information about a spatial reference
#' system passed as text in any of the formats supported by [srs_to_wkt()].
#'
#' @name srs_query
#'
#' @details
#' `srs_find_epsg()` tries to find a matching EPSG code.
#' Matching may be partial, or may fail. If `all_matches = TRUE`, returns a
#' data frame with entries sorted by decreasing match confidence (first
#' entry has the highest match confidence); the default is `FALSE` which
#' returns a character string in the form "EPSG:####" for the first match
#' (highest confidence). Wrapper of `OSRFindMatches()` in the GDAL SRS API.
#'
#' `srs_get_name()` returns the SRS name.
#' Wrapper of `OSRGetName()` in the GDAL API.
#'
#' `srs_is_geographic()` returns `TRUE` if the root is a GEOGCS node.
#' Wrapper of `OSRIsGeographic()` in the GDAL API.
#'
#' `srs_is_derived_gcs()` returns `TRUE` if the SRS is a derived geographic
#' coordinate system (for example a rotated long/lat grid).
#' Wrapper of `OSRIsDerivedGeographic()` in the GDAL API.
#'
#' `srs_is_local()` returns `TRUE` if the SRS is a local coordinate system
#' (the root is a LOCAL_CS node).
#' Wrapper of `OSRIsLocal()` in the GDAL API.
#'
#' `srs_is_projected()` returns `TRUE` if the SRS contains a PROJCS node
#' indicating a it is a projected coordinate system.
#' Wrapper of `OSRIsProjected()` in the GDAL API.
#'
#' `srs_is_compound()` returns `TRUE` if the SRS is compound.
#' Wrapper of `OSRIsCompound()` in the GDAL API.
#'
#' `srs_is_geocentric()` returns `TRUE` if the SRS is a geocentric coordinate
#' system.
#' Wrapper of `OSRIsGeocentric()` in the GDAL API.
#'
#' `srs_is_vertical()` returns `TRUE` if the SRS is a vertical coordinate
#' system.
#' Wrapper of `OSRIsVertical()` in the GDAL API.
#'
#' `srs_is_dynamic()` returns `TRUE` if the SRS is is a dynamic coordinate
#' system (relies on a dynamic datum, i.e., a datum that is not plate-fixed).
#' Wrapper of `OSRIsDynamic()` in the GDAL API. Requires GDAL >= 3.4.
#'
#' `srs_is_same()` returns `TRUE` if two spatial references describe
#' the same system.
#' Wrapper of `OSRIsSame()` in the GDAL API.
#'
#' `srs_get_angular_units()` fetches the angular geographic coordinate system
#' units. Returns a list of length two: the first element contains the unit
#' name as a character string, and the second element contains a numeric value
#' to multiply by angular distances to transform them to radians.
#' Wrapper of `OSRGetAngularUnits()` in the GDAL API.
#'
#' `srs_get_linear_units()` fetches the linear projection units.
#' Returns a list of length two: the first element contains the unit
#' name as a character string, and the second element contains a numeric value
#' to multiply by linear distances to transform them to meters.
#' If no units are available, values of "Meters" and 1.0 will be assumed.
#' Wrapper of `OSRGetLinearUnits()` in the GDAL API.
#'
#' `srs_get_coord_epoch()` returns the coordinate epoch, as decimal year
#' (e.g. 2021.3), or `0` if not set or not relevant.
#' Wrapper of `OSRGetCoordinateEpoch()` in the GDAL API. Requires GDAL >= 3.4.
#'
#' `srs_get_utm_zone()` returns the UTM zone number or zero if `srs` isn't a
#' UTM definition. A positive value indicates northern hemisphere; a negative
#' value is in the southern hemisphere.
#' Wrapper of `OSRGetUTMZone()` in the GDAL API.
#'
#' `srs_get_axis_mapping_strategy()` returns the data axis to CRS axis mapping
#' strategy as a character string, one of:
#' * `OAMS_TRADITIONAL_GIS_ORDER`: for geographic CRS with lat/long order, the
#' data will still be long/lat ordered. Similarly for a projected CRS with
#' northing/easting order, the data will still be easting/northing ordered.
#' * `OAMS_AUTHORITY_COMPLIANT`: the data axis will be identical to the CRS
#' axis.
#' * `OAMS_CUSTOM`: custom-defined data axis
#'
#' @param srs Character string containing an SRS definition in various
#' formats (e.g., WKT, PROJ.4 string, well known name such as NAD27, NAD83,
#' WGS84, etc., see [srs_to_wkt()]).
#' @param srs_other Character string containing an SRS definition in various
#' formats(see above).
#' @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`.
#' @param all_matches Logical scalar. `TRUE` to return all identified matches
#' in a data frame, including a confidence value (0-100) for each match. The
#' default is `FALSE` which returns a character string in the form
#' `"EPSG:<code>"` for the first match (highest confidence).
#'
#' @seealso
#' [srs_convert]
#'
#' @examples
#' wkt <- 'PROJCS["ETRS89 / UTM zone 32N (N-E)",
#' GEOGCS["ETRS89",
#' DATUM["European_Terrestrial_Reference_System_1989",
#' SPHEROID["GRS 1980",6378137,298.257222101,
#' AUTHORITY["EPSG","7019"]],
#' TOWGS84[0,0,0,0,0,0,0],
#' AUTHORITY["EPSG","6258"]],
#' PRIMEM["Greenwich",0,
#' AUTHORITY["EPSG","8901"]],
#' UNIT["degree",0.0174532925199433,
#' AUTHORITY["EPSG","9122"]],
#' AUTHORITY["EPSG","4258"]],
#' PROJECTION["Transverse_Mercator"],
#' PARAMETER["latitude_of_origin",0],
#' PARAMETER["central_meridian",9],
#' PARAMETER["scale_factor",0.9996],
#' PARAMETER["false_easting",500000],
#' PARAMETER["false_northing",0],
#' UNIT["metre",1,
#' AUTHORITY["EPSG","9001"]],
#' AXIS["Northing",NORTH],
#' AXIS["Easting",EAST]]'
#'
#' srs_find_epsg(wkt)
#'
#' srs_find_epsg(wkt, all_matches = TRUE)
#'
#' srs_get_name("EPSG:5070")
#'
#' srs_is_geographic("EPSG:5070")
#' srs_is_geographic("EPSG:4326")
#'
#' srs_is_derived_gcs("WGS84")
#'
#' srs_is_projected("EPSG:5070")
#' srs_is_projected("EPSG:4326")
#'
#' srs_is_compound("EPSG:4326")
#'
#' srs_is_geocentric("EPSG:7789")
#'
#' srs_is_vertical("EPSG:5705")
#'
#' f <- system.file("extdata/storml_elev.tif", package="gdalraster")
#' ds <- new(GDALRaster, f)
#'
#' ds$getProjection() |> srs_is_projected()
#' ds$getProjection() |> srs_get_utm_zone()
#' ds$getProjection() |> srs_get_angular_units()
#' ds$getProjection() |> srs_get_linear_units()
#' ds$getProjection() |> srs_get_axis_mapping_strategy()
#'
#' ds$getProjection() |> srs_is_same("EPSG:26912")
#' ds$getProjection() |> srs_is_same("NAD83")
#'
#' ds$close()
#'
#' # Requires GDAL >= 3.4
#' if (gdal_version_num() >= gdal_compute_version(3, 4, 0)) {
#' if (srs_is_dynamic("WGS84"))
#' print("WGS84 is dynamic")
#'
#' if (!srs_is_dynamic("NAD83"))
#' print("NAD83 is not dynamic")
#' }
srs_get_name <- function(srs) {
.Call(`_gdalraster_srs_get_name`, srs)
}
#' @rdname srs_query
srs_find_epsg <- function(srs, all_matches = FALSE) {
.Call(`_gdalraster_srs_find_epsg`, srs, all_matches)
}
#' @rdname srs_query
srs_is_geographic <- function(srs) {
.Call(`_gdalraster_srs_is_geographic`, srs)
}
#' @rdname srs_query
srs_is_derived_gcs <- function(srs) {
.Call(`_gdalraster_srs_is_derived_gcs`, srs)
}
#' @rdname srs_query
srs_is_local <- function(srs) {
.Call(`_gdalraster_srs_is_local`, srs)
}
#' @rdname srs_query
srs_is_projected <- function(srs) {
.Call(`_gdalraster_srs_is_projected`, srs)
}
#' @rdname srs_query
srs_is_compound <- function(srs) {
.Call(`_gdalraster_srs_is_compound`, srs)
}
#' @rdname srs_query
srs_is_geocentric <- function(srs) {
.Call(`_gdalraster_srs_is_geocentric`, srs)
}
#' @rdname srs_query
srs_is_vertical <- function(srs) {
.Call(`_gdalraster_srs_is_vertical`, srs)
}
#' @rdname srs_query
srs_is_dynamic <- function(srs) {
.Call(`_gdalraster_srs_is_dynamic`, srs)
}
#' @rdname srs_query
srs_is_same <- function(srs, srs_other, criterion = "", ignore_axis_mapping = FALSE, ignore_coord_epoch = FALSE) {
.Call(`_gdalraster_srs_is_same`, srs, srs_other, criterion, ignore_axis_mapping, ignore_coord_epoch)
}
#' @rdname srs_query
srs_get_angular_units <- function(srs) {
.Call(`_gdalraster_srs_get_angular_units`, srs)
}
#' @rdname srs_query
srs_get_linear_units <- function(srs) {
.Call(`_gdalraster_srs_get_linear_units`, srs)
}
#' @rdname srs_query
srs_get_coord_epoch <- function(srs) {
.Call(`_gdalraster_srs_get_coord_epoch`, srs)
}
#' @rdname srs_query
srs_get_utm_zone <- function(srs) {
.Call(`_gdalraster_srs_get_utm_zone`, srs)
}
#' @rdname srs_query
srs_get_axis_mapping_strategy <- function(srs) {
.Call(`_gdalraster_srs_get_axis_mapping_strategy`, srs)
}
#' 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
#'
#' public wrapper in R/transform.R
#' @noRd
.inv_project <- function(pts, srs, well_known_gcs = "") {
.Call(`_gdalraster_inv_project`, pts, srs, well_known_gcs)
}
#' Transform geospatial x/y coordinates
#'
#' public wrapper in R/transform.R
#' @noRd
.transform_xy <- function(pts, srs_from, srs_to) {
.Call(`_gdalraster_transform_xy`, pts, srs_from, srs_to)
}
#' Transform boundary
#'
#' `transform_bounds()` transforms a bounding box, densifying the edges to
#' account for nonlinear transformations along these edges and extracting
#' the outermost bounds. Wrapper of `OCTTransformBounds()` in the GDAL Spatial
#' Reference System API. Requires GDAL >= 3.4.
#'
#' @details
#' The following refer to the *output* values `xmin`, `ymin`, `xmax`, `ymax`:
#'
#' If the destination CRS is geographic, the first axis is longitude, and
#' `xmax < xmin` then the bounds crossed the antimeridian. In this scenario
#' there are two polygons, one on each side of the antimeridian. The first
#' polygon should be constructed with `(xmin, ymin, 180, ymax)` and the second
#' with `(-180, ymin, xmax, ymax)`.
#'
#' If the destination CRS is geographic, the first axis is latitude, and
#' `ymax < ymin` then the bounds crossed the antimeridian. In this scenario
#' there are two polygons, one on each side of the antimeridian. The first
#' polygon should be constructed with `(ymin, xmin, ymax, 180)` and the second
#' with `(ymin, -180, ymax, xmax)`.
#'
#' @param bbox Numeric vector of length four containing the input bounding
#' box (xmin, ymin, xmax, ymax).
#' @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()].
#' @param densify_pts Integer value giving the number of points to use to
#' densify the bounding polygon in the transformation. Recommended to use `21`
#' (the default).
#' @param traditional_gis_order Logical value, `TRUE` to use traditional GIS
#' order of axis mapping (the default) or `FALSE` to use authority compliant
#' axis order (see Note).
#' @returns Numeric vector of length four containing the bounding box in the
#' output spatial reference system (xmin, ymin, xmax, ymax).
#'
#' @seealso
#' [srs_to_wkt()]
#'
#' @note
#' `traditional_gis_order = TRUE` (the default) means that for geographic CRS
#' with lat/long order, the data will still be long/lat ordered. Similarly for
#' a projected CRS with northing/easting order, the data will still be
#' easting/northing ordered (GDAL's OAMS_TRADITIONAL_GIS_ORDER).
#'
#' `traditional_gis_order = FALSE` means that the data axis will be identical
#' to the CRS axis (GDAL's OAMS_AUTHORITY_COMPLIANT).
#'
#' See
#' \url{https://gdal.org/en/stable/tutorials/osr_api_tut.html#crs-and-axis-order}.
#'
#' @examples
#' bb <- c(-1405880.71737, -1371213.76254, 5405880.71737, 5371213.76254)
#'
#' # traditional GIS axis ordering by default (lon, lat)
#' transform_bounds(bb, "EPSG:32761", "EPSG:4326")
#'
#' # authority compliant axis ordering
#' transform_bounds(bb, "EPSG:32761", "EPSG:4326",
#' traditional_gis_order = FALSE)
transform_bounds <- function(bbox, srs_from, srs_to, densify_pts = 21L, traditional_gis_order = TRUE) {
.Call(`_gdalraster_transform_bounds`, bbox, srs_from, srs_to, densify_pts, traditional_gis_order)
}
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.