-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathwbt_source.R
More file actions
214 lines (194 loc) · 6.66 KB
/
wbt_source.R
File metadata and controls
214 lines (194 loc) · 6.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#' Initialize an R object containing spatial data for use by WhiteboxTools
#'
#' @param x A terra SpatVector or sf object (in memory) or a path to a file that
#' can be read as a SpatVectorProxy. Or a memory or file-based SpatRaster.
#' SpatRaster object. When `x` has multiple layers/bands, the first layer is
#' used by default; use the \code{layer} argument to select a specific
#' layer/band.
#' @param dsn Data source path / file name
#' @param layer Data layer. For vectors, `layer` is interpreted as a layer
#' name (character); for rasters, `layer` is interpreted as a band index or
#' name (integer OR character)
#' @param tmpdir Directory to write temporary ESRI Shapefiles for vector input
#' in memory or otherwise not already in shapefile. Default: `tempdir()`
#' @param pattern Character vector giving the initial part of the temporary file
#' name
#' @param force Force write of vector data to file? Default: FALSE (only write
#' if file does not exist and new file is needed)
#' @param verbose Print information about data source and contents?
#' @param ... Additional arguments passed to `terra::writeVector()` or
#' `sf::st_write()`, or `terra::writeRaster` (for rasters).
#' @return An R object (SpatRaster, SpatVector, SpatVectorProxy, sf) with
#' attributes `wbt_dsn` and `wbt_layer` set as needed to support reading and
#' writing R objects from file by WhiteboxTools.
#' @keywords General
#' @export
wbt_source <- function(x,
dsn = NULL,
layer = NULL,
force = FALSE,
tmpdir = tempdir(),
pattern = "wbt",
verbose = wbt_verbose(),
...) {
if (length(layer) > 1) {
stop("argument `layer` must have length 1 or 0 (NULL)", call. = FALSE)
}
.check_pkg_ns <- function(pkg) {
if (!requireNamespace(pkg)) {
stop("package `", pkg, "` is required to convert to `wbt()`-compatible data sources", call. = FALSE)
}
}
if (is.character(x)) {
if (file.exists(x)) {
.check_pkg_ns("terra")
# convert to shapefile if needed
x2 <- try(terra::vect(x, layer = ifelse(is.null(layer), "", layer), proxy = TRUE), silent = TRUE)
fp <- file.path(tmpdir, paste0(basename(x), "_", basename(tempfile(pattern = pattern))))
if (!inherits(x2, 'try-error') && !grepl("\\.shp$", x, ignore.case = TRUE)) {
fp <- paste0(fp, ".shp")
if (terra::writeVector(terra::query(x2), fp)) {
x <- fp
} else {
stop("Failed to convert `x` (", x, ") to Shapefile.")
}
} else if (inherits(x2, 'try-error')) {
if (!grepl("\\.tiff?$", x, ignore.case = TRUE) || length(layer) > 0) {
# try reading a raster file and writing to geotiff
fp <- paste0(fp, ".tif")
if (length(layer) > 0) {
x2 <- terra::rast(x, lyrs = layer[1])
} else {
x2 <- terra::rast(x)
}
if (terra::writeRaster(x2, fp)) {
x <- fp
} else {
stop("Failed to convert `x` (", x, ") to GeoTIFF")
}
}
x <- terra::rast(x)
}
if (!inherits(x, 'SpatRaster')) {
# a SpatVectorProxy allows us to get some basic info without loading the whole file
x <- terra::vect(x, proxy = TRUE)
}
if (is.character(x) && !file.exists(x)) {
stop("File (", x, ") does not exist")
}
if (!inherits(x, c("SpatRaster", "SpatVectorProxy"))) {
stop("Unhandled input object type")
}
attr(x, 'wbt_dsn') <- terra::sources(x)
attr(x, 'wbt_layer') <- layer
return(x)
}
}
ext <- ".shp"
if (inherits(x, c('SpatRaster', 'RasterLayer',
'RasterStack', 'RasterBrick'))) {
.check_pkg_ns("terra")
if (!inherits(x, 'SpatRaster')) {
x <- terra::rast(x)
}
ext <- ".tif"
src <- terra::sources(x)
if (length(src) > 0 && any(nzchar(src))) {
if (length(src) > 1) {
message("Object 'x' has multiple source files; using first non-empty source path")
}
dsn <- src[which(nzchar(src))[1]]
}
}
# NULL dsn (TODO: GDAL-supported dsn not supported by WBT)
if (is.null(dsn)) {
# if (gpkg) {
# # default geopackage file paths
# dsn <- wbt_geopackage()
# layer <- wbt_geopackage_layer()
# } else {
# only supported vector format is the ESRI Shapefile.
# TODO: dbf limitations? use alternate wbt/gdal common format?
if (!is.null(layer)) {
bn <- paste0(pattern, "_", layer)
} else {
bn <- pattern
}
dsn <- tempfile(pattern = bn, tmpdir = tmpdir, fileext = ext)
# }
}
if (!file.exists(dsn) || force) {
# write to file/db
if (inherits(x, c('SpatVector', 'SpatVectorProxy', 'SpatRaster'))) {
.check_pkg_ns("terra")
if (inherits(x, 'SpatVectorProxy')) {
x <- terra::query(x)
}
if (inherits(x, 'SpatVector')) {
terra::writeVector(x,
filename = dsn,
layer = layer,
overwrite = force,
...)
} else if (inherits(x, 'SpatRaster')) {
terra::writeRaster(x, filename = dsn, overwrite = force, ...)
}
} else {
.check_pkg_ns("sf")
# convert less common types to core types
if (inherits(x, 'sfc') || inherits(x, 'Spatial')) {
x <- sf::st_as_sf(x)
}
if (inherits(x, 'sf')) {
sf::st_write(
x,
dsn = dsn,
layer = layer,
quiet = !verbose,
delete_dsn = force,
...
)
}
}
}
# set attributes
# TODO: support for DBIConnection as dsn?
if (file.exists(dsn)) {
# TODO: check layer exists in DSN?
if (!is.null(layer)) {
# ...
}
# TODO: check file metadata/extent/CRS/etc?
attr(x, 'wbt_dsn') <- dsn
attr(x, 'wbt_layer') <- layer
}
x
}
# draft, non-exported functions for generating paths/layers in a "scratch" geopackage
wbt_geopackage <- function(wd = wbt_wd(),
gpkg = "Default.gpkg") {
if (wd == "")
wd <- getwd()
file.path(wd, gpkg)
}
wbt_geopackage_layer <- function(layer = NULL) {
basename(tempfile(pattern = "layer"))
}
wbt_add2 <- function(input1,
input2,
output,
wd = getOption("whitebox.wd", getwd()),
verbose_mode = wbt_verbose(),
compress_rasters = wbt_compress_rasters(),
...) {
wbt(
"add",
input1 = input1,
input2 = input2,
output = output,
# wd = wd,
# verbose_mode = verbose_mode,
# compress_rasters = compress_rasters,
...
)
}