From 1fabce1e68915fe101b44278686ae09c2ed75d54 Mon Sep 17 00:00:00 2001 From: rhijmans Date: Tue, 10 Oct 2023 01:54:56 -0700 Subject: [PATCH] fixes #1304 --- NAMESPACE | 2 +- R/Agenerics.R | 3 +++ R/generics.R | 28 +++++++++++++++++++++++++ man/tags.Rd | 51 ++++++++++++++++++++++++++++++++++++++++++++++ src/RcppModule.cpp | 3 +++ src/spatRaster.cpp | 35 +++++++++++++++++++++++++++++++ src/spatRaster.h | 6 ++++++ 7 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 man/tags.Rd diff --git a/NAMESPACE b/NAMESPACE index 51f84deae..4128b565c 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, forceCCW, 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, is.rotated, isTRUE, isFALSE, is.empty, 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) +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, forceCCW, 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, is.rotated, isTRUE, isFALSE, is.empty, 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, "set.tags", tags, 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 b41f1d21f..b1ba05872 100644 --- a/R/Agenerics.R +++ b/R/Agenerics.R @@ -1,5 +1,8 @@ #if (!isGeneric("#")) { setGeneric("#", function(x, ...) standardGeneric("#")) } +if (!isGeneric("tags")) {setGeneric("tags", function(x, ...) standardGeneric("tags"))} +if (!isGeneric("set.tags")) {setGeneric("set.tags", function(x, ...) standardGeneric("set.tags"))} + if (!isGeneric("forceCCW")) {setGeneric("forceCCW", function(x, ...) standardGeneric("forceCCW"))} if (!isGeneric("addCats")) {setGeneric("addCats", function(x, ...) standardGeneric("addCats"))} if (!isGeneric("regress")) {setGeneric("regress", function(y, x, ...) standardGeneric("regress"))} diff --git a/R/generics.R b/R/generics.R index 2bf3e0109..77fd52ceb 100644 --- a/R/generics.R +++ b/R/generics.R @@ -3,6 +3,34 @@ # Version 1.0 # License GPL v3 +setMethod("tags", signature(x="SpatRaster"), + function(x) { + v <- x@cpp$getTags() + matrix(v, ncol=2, byrow=TRUE, dimnames = list(NULL, c("name", "value"))) + } +) + +setMethod("set.tags", signature(x="SpatRaster"), + function(x, name, value) { + if (is.null(name)) { + v <- tags(x) + v[,2] <- "" + } else { + if (is.null(value)) value <- "" + v <- cbind(name, value) + v[is.na(v)] <- "" + } + x <- deepcopy(x) + if (nrow(v) > 0) { + out <- sapply(1:nrow(v), function(i) { + x@cpp$addTag(v[i,1], v[i,2]) + }) + } + x + } +) + + setMethod("is.rotated", signature(x="SpatRaster"), function(x) { x@cpp$is_rotated() diff --git a/man/tags.Rd b/man/tags.Rd new file mode 100644 index 000000000..c5c257767 --- /dev/null +++ b/man/tags.Rd @@ -0,0 +1,51 @@ +\name{tags} + +\alias{tags} +\alias{tags,SpatRaster-method} +\alias{set.tags} +\alias{set.tags,SpatRaster-method} + + +\title{Set or get tags to a SpatRaster} + +\description{ +You can set arbitrary tags to a SpatRaster. Each tag has a name and a value. +} + +\usage{ +\S4method{set.tags}{SpatRaster}(x, name, value) + +\S4method{tags}{SpatRaster}(x) +} + +\arguments{ +\item{x}{SpatRaster} + +\item{name}{character} + +\item{value}{character} +} + +\value{ +SpatRaster (\code{set.tags}) or matrix (\code{tags}) +} + +\examples{ +r <- rast() +r <- set.tags(r, c("one", "two", "three"), c("ABC", "123", "hello")) +tags(r) + +r <- set.tags(r, "another_tag", "another_value") +tags(r) + +# remove one tag +r <- set.tags(r, c("one"), c("")) +tags(r) + +# remove all tags +r <- set.tags(r, NULL) +tags(r) +} + +\keyword{spatial} + diff --git a/src/RcppModule.cpp b/src/RcppModule.cpp index 0d8a10da3..f94c58443 100644 --- a/src/RcppModule.cpp +++ b/src/RcppModule.cpp @@ -638,6 +638,9 @@ RCPP_MODULE(spat){ .method("getWarnings", &SpatRaster::getWarnings) .method("getMessage", &SpatRaster::getMessage) + .method("addTag", &SpatRaster::addTag) + .method("getTags", &SpatRaster::getTags) + //.field("name", &SpatRaster::name) .method("getFileBlocksize", &SpatRaster::getFileBlocksize) diff --git a/src/spatRaster.cpp b/src/spatRaster.cpp index 93e6ee5a8..82ceca623 100644 --- a/src/spatRaster.cpp +++ b/src/spatRaster.cpp @@ -2567,3 +2567,38 @@ std::vector SpatRaster::getFileBlocksize() { } +bool SpatRaster::addTag(std::string name, std::string value) { + lrtrim(name); + lrtrim(value); + if (value == "") { + return removeTag(name); + } else if (name != "") { + tags[name] = value; + return true; + } + return false; +} + +bool SpatRaster::removeTag(std::string name) { + std::map::iterator it = tags.find(name); + if (it == tags.end()) return false; + tags.erase(it); + return true; +} + +std::string SpatRaster::getTag(std::string name) { + std::map::iterator it = tags.find(name); + if (it != tags.end()) return it->second; + return ""; +} + +std::vector SpatRaster::getTags() { + std::vector out; + out.reserve(2 * tags.size()); + for(auto e : tags) { + out.push_back(e.first); + out.push_back(e.second); + } + return out; +} + diff --git a/src/spatRaster.h b/src/spatRaster.h index 941dbca5e..6bab26735 100644 --- a/src/spatRaster.h +++ b/src/spatRaster.h @@ -227,6 +227,12 @@ class SpatRaster { std::string getError() { return msg.getError();} std::string getMessage() { return msg.getMessage();} + std::map tags; + bool addTag(std::string name, std::string value); + bool removeTag(std::string name); + std::string getTag(std::string name); + std::vector getTags(); + //double NA = std::numeric_limits::quiet_NaN(); size_t ncol();