From 44751fba5438c898bd10e7d9fd665c8642ce075e Mon Sep 17 00:00:00 2001 From: rhijmans Date: Sun, 14 May 2023 11:23:12 -0700 Subject: [PATCH] for #1150 --- DESCRIPTION | 2 +- NAMESPACE | 2 +- R/Agenerics.R | 1 + R/pack.R | 384 --------------------------------------------- R/values.R | 4 + man/wrap.Rd | 4 +- src/RcppModule.cpp | 1 + src/spatRaster.cpp | 11 ++ src/spatRaster.h | 2 + 9 files changed, 22 insertions(+), 389 deletions(-) delete mode 100644 R/pack.R diff --git a/DESCRIPTION b/DESCRIPTION index 47d3d387c..e28df2999 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,7 @@ Package: terra Type: Package Title: Spatial Data Analysis Version: 1.7-33 -Date: 2023-05-12 +Date: 2023-05-14 Depends: R (>= 3.5.0) Suggests: parallel, tinytest, ncdf4, sf (>= 0.9-8), deldir, XML, leaflet, htmlwidgets LinkingTo: Rcpp diff --git a/NAMESPACE b/NAMESPACE index 707fdb13b..9b8006172 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,7 +1,7 @@ useDynLib(terra, .registration=TRUE) import(methods, Rcpp) exportClasses(SpatExtent, SpatRaster, SpatRasterDataset, SpatRasterCollection, SpatVector, SpatVectorProxy, SpatVectorCollection) -exportMethods("[", "[[", "!", "%in%", activeCat, "activeCat<-", "add<-", addCats, adjacent, all.equal, aggregate, allNA, align, animate, anyNA, app, area, Arith, approximate, as.bool, as.int, as.contour, as.lines, as.points, as.polygons, as.raster, as.array, as.data.frame, as.factor, as.list, as.logical, as.matrix, as.numeric, atan2, atan_2, autocor, barplot, blocks, boundaries, boxplot, buffer, cartogram, categories, cats, catalyze, clamp, clamp_ts, classify, clearance, cellSize, cells, cellFromXY, cellFromRowCol, cellFromRowColCombine, centroids, click, colFromX, colFromCell, colorize, coltab, "coltab<-", combineGeoms, compare, concats, Compare, compareGeom, contour, convHull, countNA, costDist, crds, cover, crop, crosstab, crs, "crs<-", datatype, deepcopy, delaunay, densify, density, depth, "depth<-", describe, diff, disagg, direction, distance, dots, draw, droplevels, elongate, emptyGeoms, erase, extend, ext, "ext<-", extract, expanse, fillHoles, fillTime, flip, focal, focal3D, focalCor, focalPairs, focalReg, focalCpp, focalValues, freq, gaps, geom, geomtype, global, gridDist, gridDistance, has.colors, has.RGB, hasMinMax, hasValues, hist, head, ifel, impose, init, image, inext, interpIDW, interpNear, inMemory, inset, interpolate, intersect, is.bool, is.int, is.lonlat, isTRUE, isFALSE, is.factor, is.lines, is.points, is.polygons, is.related, is.valid, lapp, layerCor, levels, linearUnits, lines, Logic, varnames, "varnames<-", logic, longnames, "longnames<-", makeValid, mask, match, math, Math, Math2, mean, median, meta, merge, mergeLines, mergeTime, minmax, minRect, modal, mosaic, na.omit, not.na, NAflag, "NAflag<-", nearby, nearest, ncell, ncol, "ncol<-", nlyr, "nlyr<-", noNA, normalize.longitude, nrow, "nrow<-", nsrc, origin, "origin<-", pairs, panel, patches, perim, persp, plot, plotRGB, plet, RGB, "RGB<-", polys, points, predict, project, quantile, query, rangeFill, rapp, rast, rasterize, rasterizeGeom, rasterizeWin,readStart, readStop, readValues, rectify, regress, relate, removeDupNodes, res, "res<-", resample, rescale, rev, rcl, roll, rotate, rowFromY, rowColCombine, rowColFromCell, rowFromCell, sapp, scale, scoff, "scoff<-", sds, sort, sprc, sel, selectRange, setMinMax, setValues, segregate, selectHighest, set.cats, set.crs, set.ext, set.names, set.RGB, set.values, size, sharedPaths, shift, sieve, simplifyGeom, snap, sources, spatSample, split, spin, stdev, stretch, subset, subst, summary, Summary, svc, symdif, t, tail, tapp, terrain, tighten, makeNodes, makeTiles, time, timeInfo, "time<-", text, trans, trim, units, union, "units<-", unique, unwrap, update, vect, values, "values<-", viewshed, voronoi, vrt, weighted.mean, where.min, where.max, which.lyr, which.min, which.max, which.lyr, width, window, "window<-", writeCDF, writeRaster, wrap, writeStart, writeStop, writeVector, writeValues, xmin, xmax, "xmin<-", "xmax<-", xres, xFromCol, xyFromCell, xFromCell, ymin, ymax, "ymin<-", "ymax<-", yres, yFromCell, yFromRow, zonal, zoom, cbind2, readRDS, saveRDS, unserialize, serialize) +exportMethods("[", "[[", "!", "%in%", activeCat, "activeCat<-", "add<-", addCats, adjacent, all.equal, aggregate, allNA, align, animate, anyNA, app, area, Arith, approximate, as.bool, as.int, as.contour, as.lines, as.points, as.polygons, as.raster, as.array, as.data.frame, as.factor, as.list, as.logical, as.matrix, as.numeric, atan2, atan_2, autocor, barplot, blocks, boundaries, boxplot, buffer, cartogram, categories, cats, catalyze, clamp, clamp_ts, classify, clearance, cellSize, cells, cellFromXY, cellFromRowCol, cellFromRowColCombine, centroids, click, colFromX, colFromCell, colorize, coltab, "coltab<-", combineGeoms, compare, concats, Compare, compareGeom, contour, convHull, countNA, costDist, crds, cover, crop, crosstab, crs, "crs<-", datatype, deepcopy, delaunay, densify, density, depth, "depth<-", describe, diff, disagg, direction, distance, dots, draw, droplevels, elongate, emptyGeoms, erase, extend, ext, "ext<-", extract, expanse, fillHoles, fillTime, flip, focal, focal3D, focalCor, focalPairs, focalReg, focalCpp, focalValues, freq, gaps, geom, geomtype, global, gridDist, gridDistance, has.colors, has.RGB, hasMinMax, hasValues, hist, head, ifel, impose, init, image, inext, interpIDW, interpNear, inMemory, inset, interpolate, intersect, is.bool, is.int, is.lonlat, isTRUE, isFALSE, is.factor, is.lines, is.points, is.polygons, is.related, is.valid, lapp, layerCor, levels, linearUnits, lines, Logic, varnames, "varnames<-", logic, longnames, "longnames<-", makeValid, mask, match, math, Math, Math2, mean, median, meta, merge, mergeLines, mergeTime, minmax, minRect, modal, mosaic, na.omit, not.na, NAflag, "NAflag<-", nearby, nearest, ncell, ncol, "ncol<-", nlyr, "nlyr<-", noNA, normalize.longitude, nrow, "nrow<-", nsrc, origin, "origin<-", pairs, panel, patches, perim, persp, plot, plotRGB, plet, RGB, "RGB<-", polys, points, predict, project, quantile, query, rangeFill, rapp, rast, rasterize, rasterizeGeom, rasterizeWin,readStart, readStop, readValues, rectify, regress, relate, removeDupNodes, res, "res<-", resample, rescale, rev, rcl, roll, rotate, rowFromY, rowColCombine, rowColFromCell, rowFromCell, sapp, scale, scoff, "scoff<-", sds, sort, sprc, sel, selectRange, setMinMax, setValues, segregate, selectHighest, set.cats, set.crs, set.ext, set.names, set.RGB, set.values, size, sharedPaths, shift, sieve, simplifyGeom, snap, sources, spatSample, split, spin, stdev, stretch, subset, subst, summary, Summary, svc, symdif, t, tail, tapp, terrain, tighten, makeNodes, makeTiles, time, timeInfo, "time<-", text, trans, trim, units, union, "units<-", unique, unwrap, update, vect, values, "values<-", viewshed, voronoi, vrt, weighted.mean, where.min, where.max, which.lyr, which.min, which.max, which.lyr, width, window, "window<-", writeCDF, writeRaster, wrap, wrapCache, writeStart, writeStop, writeVector, writeValues, xmin, xmax, "xmin<-", "xmax<-", xres, xFromCol, xyFromCell, xFromCell, ymin, ymax, "ymin<-", "ymax<-", yres, yFromCell, yFromRow, zonal, zoom, cbind2, readRDS, saveRDS, unserialize, serialize) S3method(cbind, SpatVector) S3method(rbind, SpatVector) diff --git a/R/Agenerics.R b/R/Agenerics.R index 2bcccff1e..4d82d0f84 100644 --- a/R/Agenerics.R +++ b/R/Agenerics.R @@ -188,6 +188,7 @@ if (!isGeneric("minmax")) {setGeneric("minmax", function(x, ...) standardGeneric if (!isGeneric("nsrc")) { setGeneric("nsrc", function(x) standardGeneric("nsrc")) } if (!isGeneric("perim")) {setGeneric("perim", function(x, ...) standardGeneric("perim"))} if (!isGeneric("project")) {setGeneric("project", function(x,...) standardGeneric("project"))} +if (!isGeneric("wrapCache")) {setGeneric("wrapCache", function(x, ...) standardGeneric("wrapCache"))} if (!isGeneric("wrap")) {setGeneric("wrap", function(x, ...) standardGeneric("wrap"))} if (!isGeneric("unwrap")) {setGeneric("unwrap", function(x, ...) standardGeneric("unwrap"))} if (!isGeneric("cats")) { setGeneric("cats", function(x, ...) standardGeneric("cats")) } diff --git a/R/pack.R b/R/pack.R deleted file mode 100644 index b92496f3e..000000000 --- a/R/pack.R +++ /dev/null @@ -1,384 +0,0 @@ - - -setClass("PackedSpatVector", - representation ( - type = "character", - crs = "character", - coordinates = "matrix", - index = "matrix", - attributes = "data.frame" - ), - prototype ( - type= "", - crs = "" - ) -) - - -setClass("PackedSpatRaster", - representation ( - definition = "character", - values = "matrix", - attributes = "list" - ), - prototype ( - attributes = list() - ) -) - -setClass("PackedSpatRasterDC", - representation ( - type = "character", - rasters = "list" - ), - prototype ( - rasters = list() - ) -) - - - -setMethod("wrap", signature(x="SpatVector"), - function(x) { - vd <- methods::new("PackedSpatVector") - vd@type <- geomtype(x) - vd@crs <- as.character(crs(x)) - #stopifnot(vd@type %in% c("points", "lines", "polygons")) - g <- geom(x) - vd@coordinates <- g[, c("x", "y"), drop=FALSE] - j <- c(1, 2, grep("hole", colnames(g))) - g <- g[ , j, drop=FALSE] - i <- which(!duplicated(g)) - vd@index <- cbind(g[i, ,drop=FALSE], start=i) - vd@attributes <- as.data.frame(x) - vd - } -) - - -setMethod("unwrap", signature(x="PackedSpatVector"), - function(x) { - p <- methods::new("SpatVector") - p@pnt <- SpatVector$new() - if (!is.na(x@crs)) { - crs(p, warn=FALSE) <- x@crs - } - if (nrow(x@coordinates) == 0) { - return(p) - } - - n <- ncol(x@index) - reps <- diff(c(x@index[,n], nrow(x@coordinates)+1)) - i <- rep(1:nrow(x@index), reps) - if (n == 2) { - p@pnt$setGeometry(x@type, x@index[i,1], x@index[i,2], x@coordinates[,1], x@coordinates[,2], rep(0, nrow(x@coordinates))) - } else { - p@pnt$setGeometry(x@type, x@index[i,1], x@index[i,2], x@coordinates[,1], x@coordinates[,2], x@index[i,3]) - } - if (nrow(x@attributes) > 0) { - values(p) <- x@attributes - } - messages(p, "pack") - } -) - -setMethod("vect", signature(x="PackedSpatVector"), - function(x) { - unwrap(x) - } -) - - -setMethod("show", signature(object="PackedSpatVector"), - function(object) { - print(paste("This is a", class(object), "object. Use 'terra::unwrap()' to unpack it")) - } -) - - - -setMethod("as.character", signature(x="SpatRaster"), - function(x) { - e <- as.vector(ext(x)) - d <- crs(x, describe=TRUE) - if (!(is.na(d$authority) || is.na(d$code))) { - crs <- paste0(", crs='", d$authority, ":", d$code, "'") - } else { - d <- crs(x) - crs <- ifelse(d=="", ", crs=''", paste0(", crs='", d, "'")) - crs <- gsub("\n[ ]+", "", crs) - } - nms <- paste0(", names=c('", paste(names(x), collapse="', '"), "')") - paste0("rast(", - "ncols=", ncol(x), - ", nrows=", nrow(x), - ", nlyrs=", nlyr(x), - ", xmin=",e[1], - ", xmax=",e[2], - ", ymin=",e[3], - ", ymax=",e[4], - nms, - crs, ")" - ) - } -) -#eval(parse(text=as.character(s))) - - -setMethod("wrap", signature(x="SpatRaster"), - function(x, proxy=FALSE, path=NULL, overwrite=FALSE) { - r <- methods::new("PackedSpatRaster") - r@definition <- as.character(x) - - opt <- spatOptions(ncopies=2) - can <- (!proxy) && x@pnt$canProcessInMemory(opt) - - s <- sources(x) - if (can || (all(s == ""))) { - r@values <- values(x) - } else if (all(s != "")) { - xs <- sources(x, TRUE, TRUE) - if (!is.null(path)) { - path <- normalizePath(path, mustWork=TRUE) - fnames <- file.path(path, basename(s)) - fex <- file.exists(fnames) - if (isTRUE(overwrite)) { - #i <- s != fnames - file.copy(s, fnames) - } else if (isFALSE(overwrite) && (any(fex))) { - error("wrap", "file exists and 'overwrite=FALSE'") - } else if (!all(fex)) { - file.copy(s[!fex], fnames[!fex]) - } - xs$source <- fnames - } - r@attributes$sources <- xs - } else { - fname <- paste0(tempfile(), ".tif") - if (!is.null(path)) { - path <- normalizePath(path, mustWork=TRUE) - fname <- file.path(path, basename(fname)) - } - x <- writeRaster(x, fname) - r@attributes$filename <- fname - } - - if (any(is.factor(x))) { - r@attributes$levels <- cats(x) - r@attributes$levindex <- activeCat(x, 0) - } - v <- time(x) - if (any(!is.na(v))) { - r@attributes$time <- v - r@attributes$tinfo <- timeInfo(x) - } - v <- units(x) - if (all(v != "")) { - r@attributes$units <- v - } - v <- depth(x) - if (!all(v ==0)) { - r@attributes$depth <- v - } - r - } -) - - -setMethod("unwrap", signature(x="PackedSpatRaster"), - function(x) { - - r <- eval(parse(text=x@definition)) - if (!is.null(x@attributes$filename)) { # single file, all layers - rr <- rast(x@attributes$filename) - ext(rr) <- ext(r) - crs(rr, warn=FALSE) <- crs(r) - names(rr) <- names(r) - r <- rr - } else if (!is.null(x@attributes$sources)) { - s <- x@attributes$sources - u <- unique(s$sid) - rr <- lapply(1:length(u), function(i) { - ss <- s[s$sid == i, ] - r <- rast(ss[1,2]) - r[[ss[,3]]] - }) - rr <- rast(rr) - ext(rr) <- ext(r) - crs(rr, warn=FALSE) <- crs(r) - names(rr) <- names(r) - r <- rr - } else { - values(r) <- x@values - } - - if (length(x@attributes) > 0) { - nms <- names(x@attributes) - if ("time" %in% nms) { - tinfo <- x@attributes$tinfo - if (!is.null(tinfo)) { - time(r, tinfo$step) <- x@attributes$time - } else { - time(r) <- x@attributes$time - } - } - if (any(nms %in% c("levels", "units", "depth"))) { - time(r) <- x@attributes$time - units(r) <- x@attributes$units - depth(r) <- x@attributes$depth - if (!is.null(x@attributes$levels)) { - if (is.null(x@attributes$levindex)) x@attributes$levindex <- 1 - set.cats(r, layer=0, x@attributes$levels, active=x@attributes$levindex) - } - } - } - r - } -) - - -setMethod("wrap", signature(x="SpatRasterDataset"), - function(x, proxy=FALSE) { - r <- methods::new("PackedSpatRasterDC") - r@type <- "SpatRasterDataset" - r@rasters <- lapply(x, wrap) - r - } -) - -setMethod("wrap", signature(x="SpatRasterCollection"), - function(x, proxy=FALSE) { - r <- methods::new("PackedSpatRasterDC") - r@type <- "SpatRasterCollection" - r@rasters <- lapply(x, wrap) - r - } -) - -setMethod("unwrap", signature(x="PackedSpatRasterDC"), - function(x) { - type <- x@type - x <- lapply(x@rasters, unwrap) - if (type == "SpatRasterCollection") { - sprc(x) - } else { - sds(x) - } - } -) - - - -setMethod("rast", signature(x="PackedSpatRaster"), - function(x) { - unwrap(x) - } -) - -setMethod("show", signature(object="PackedSpatRaster"), - function(object) { - print(paste("This is a", class(object), "object. Use 'terra::unwrap()' to unpack it")) - } -) - -setMethod("show", signature(object="PackedSpatRasterDC"), - function(object) { - print(paste("This is a", class(object), "object. Use 'terra::unwrap()' to unpack it")) - } -) - - -setMethod("unwrap", signature(x="ANY"), - function(x) { - x - } -) - - -setMethod("serialize", signature(object="SpatVector"), - function(object, connection, ascii = FALSE, xdr = TRUE, version = NULL, refhook = NULL) { - object = wrap(object) - serialize(object, connection=connection, ascii = ascii, xdr = xdr, version = version, refhook = refhook) - } -) - - -setMethod("saveRDS", signature(object="SpatVector"), - function(object, file="", ascii = FALSE, version = NULL, compress=TRUE, refhook = NULL) { - object = wrap(object) - saveRDS(object, file=file, ascii = ascii, version = version, compress=compress, refhook = refhook) - } -) - - -setMethod("serialize", signature(object="SpatRaster"), - function(object, connection, ascii = FALSE, xdr = TRUE, version = NULL, refhook = NULL) { - object <- wrap(object, proxy=TRUE) - serialize(object, connection=connection, ascii = ascii, xdr = xdr, version = version, refhook = refhook) - } -) - -setMethod("serialize", signature(object="SpatRasterDataset"), - function(object, connection, ascii = FALSE, xdr = TRUE, version = NULL, refhook = NULL) { - object <- wrap(object, proxy=TRUE) - serialize(object, connection=connection, ascii = ascii, xdr = xdr, version = version, refhook = refhook) - } -) - -setMethod("serialize", signature(object="SpatRasterCollection"), - function(object, connection, ascii = FALSE, xdr = TRUE, version = NULL, refhook = NULL) { - object <- wrap(object, proxy=TRUE) - serialize(object, connection=connection, ascii = ascii, xdr = xdr, version = version, refhook = refhook) - } -) - - -setMethod("unserialize", signature(connection="ANY"), - function(connection, refhook = NULL) { - x <- base::unserialize(connection, refhook) - unwrap(x) - } -) - - - -setMethod("saveRDS", signature(object="SpatRaster"), - function(object, file="", ascii = FALSE, version = NULL, compress=TRUE, refhook = NULL) { - object <- wrap(object) - saveRDS(object, file=file, ascii = ascii, version = version, compress=compress, refhook = refhook) - } -) - -setMethod("saveRDS", signature(object="SpatRasterDataset"), - function(object, file="", ascii = FALSE, version = NULL, compress=TRUE, refhook = NULL) { - object <- wrap(object) - saveRDS(object, file=file, ascii = ascii, version = version, compress=compress, refhook = refhook) - } -) - -setMethod("saveRDS", signature(object="SpatRasterCollection"), - function(object, file="", ascii = FALSE, version = NULL, compress=TRUE, refhook = NULL) { - object <- wrap(object) - saveRDS(object, file=file, ascii = ascii, version = version, compress=compress, refhook = refhook) - } -) - - -setMethod("readRDS", signature(file="character"), - function (file = "", refhook = NULL) { - x <- base::readRDS(file=file, refhook=refhook) - unwrap(x) - } -) - - - -#setMethod("wrap", signature(x="Spatial"), -# function(x) { -# pv <- .packVector(x) -# if (methods::.hasSlot(x, "data")) { -# pv@attributes <- x@data -# } -# pv -# } -#) diff --git a/R/values.R b/R/values.R index b7394b461..1c72c1213 100644 --- a/R/values.R +++ b/R/values.R @@ -253,6 +253,10 @@ setMethod("inMemory", signature(x="SpatRaster"), #..inMemory <- function(x) { x@pnt$inMemory } #..filenames <- function(x) { x@pnt$filenames } +subsetSource <- function(x, i) { + x@pnt <- x@pnt$subsetSource(i-1) + messages(x) +} setMethod("sources", signature(x="SpatRaster"), function(x, nlyr=FALSE, bands=FALSE) { diff --git a/man/wrap.Rd b/man/wrap.Rd index 7510c1faf..98641a6dd 100644 --- a/man/wrap.Rd +++ b/man/wrap.Rd @@ -20,7 +20,7 @@ Use \code{wrap} to pack a SpatVector or SpatRaster* to create a Packed* object. } \usage{ -\S4method{wrap}{SpatRaster}(x, proxy=FALSE, path=NULL, overwrite=FALSE) +\S4method{wrap}{SpatRaster}(x, proxy=FALSE) \S4method{wrap}{SpatRasterDataset}(x, proxy=FALSE) @@ -34,8 +34,6 @@ Use \code{wrap} to pack a SpatVector or SpatRaster* to create a Packed* object. \arguments{ \item{x}{SpatVector, SpatRaster, SpatRasterDataset or SpatRasterCollection} \item{proxy}{logical. If \code{FALSE} raster cell values are forced to memory if possible. If \code{TRUE}, a reference to source filenames is stored for data sources that are not in memory} - \item{path}{character. If not \code{NULL}, the path where raster files are copied to. This should normally not be used} - \item{overwrite}{Should existing files be overwritten when \code{path} is not \code{NULL}? If this value is not TRUE or FALSE, only files that do not exist are copied} } \value{ diff --git a/src/RcppModule.cpp b/src/RcppModule.cpp index f51a78d63..615aa215f 100644 --- a/src/RcppModule.cpp +++ b/src/RcppModule.cpp @@ -751,6 +751,7 @@ RCPP_MODULE(spat){ .method("setUnit", &SpatRaster::setUnit) .method("set_resolution", &SpatRaster::setResolution) .method("subset", &SpatRaster::subset) + .method("subsetSource", &SpatRaster::subsetSource) .method("cellFromXY", ( std::vector (SpatRaster::*)(std::vector,std::vector, double) )( &SpatRaster::cellFromXY )) .method("vectCells", &SpatRaster::vectCells) diff --git a/src/spatRaster.cpp b/src/spatRaster.cpp index 2e2efc4f5..be944de99 100644 --- a/src/spatRaster.cpp +++ b/src/spatRaster.cpp @@ -126,6 +126,17 @@ SpatRaster SpatRaster::dropSource() { } */ + +SpatRaster SpatRaster::subsetSource(size_t snr) { + if (snr >= source.size()) { + SpatRaster out; + out.setError("invalid source number"); + return out; + } + SpatRaster out(source[snr]); + return out; +} + bool SpatRaster::hasValues() { // if (source.size() == 0) { // return false; diff --git a/src/spatRaster.h b/src/spatRaster.h index 664dd7983..f8a391c84 100644 --- a/src/spatRaster.h +++ b/src/spatRaster.h @@ -361,6 +361,7 @@ class SpatRaster { bool constructFromFile(std::string fname, std::vector subds, std::vector subdsname, std::vector drivers, std::vector options); bool constructFromFileMulti(std::string fname, std::vector sub, std::vector subname, std::vector drivers, std::vector options, std::vector xyz); bool constructFromSDS(std::string filename, std::vector meta, std::vector subds, std::vector subdsname, std::vector options, std::string driver); + //SpatRaster fromFiles(std::vector fname, std::vector subds, std::vector subdsname, std::string drivers, std::vector options); @@ -371,6 +372,7 @@ class SpatRaster { SpatRaster combineSources(SpatRaster &x, bool warn); void combine(SpatRaster &x); + SpatRaster subsetSource(size_t snr); SpatRaster subset(std::vector lyrs, SpatOptions &opt); SpatRaster replace(SpatRaster x, unsigned layer, SpatOptions &opt); ////////////////////////////////////////////////////