From 2ed1ad505c1fba2391cbe4b494985d2bf66d1f71 Mon Sep 17 00:00:00 2001
From: Michael Sumner <mdsumner@gmail.com>
Date: Fri, 3 Nov 2023 11:34:04 +1100
Subject: [PATCH] tweaks

---
 NEWS.md                             |  7 +++++++
 R/fasterize.R                       | 25 ++++++++++++++++++++-----
 man/fasterize.Rd                    |  5 +++--
 src/check_inputs.cpp                |  2 +-
 tests/testthat/test-01-inputcheck.R |  6 ++++--
 tests/testthat/test-05-by.R         |  3 ++-
 6 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index 9ad62a7..61f9ef0 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,12 @@
 # fasterize 1.0.5
 
+* Input geometries may now be of type "sfc_GEOMETRY" or other mixed types. Any non polygon
+ geometry is dropped with a message. 
+ 
+* 'field' may now be a numeric, integer, or factor vector or (as before) a name of a column in 
+  the input data frame. This means we can `fasterize(vec, r, field = seq_along(vec))` or
+  `fasterize(df, r, field = seq_len(dim(df)[1L]))` or with any values we like. 
+
 * Now supporting any geometry or dataframe input supported by wk (wkb, wkt, geos, as well as sf). 
 
 * Namespaced documentation fixes thanks to CRAN. 
diff --git a/R/fasterize.R b/R/fasterize.R
index 6006477..ad0a3db 100644
--- a/R/fasterize.R
+++ b/R/fasterize.R
@@ -25,9 +25,10 @@ make_sf <- function(x, attr = NULL) {
 #' Can be created with [raster::raster()].
 #' The fasterize package provides a method to create a raster object from
 #' an polygon dataset.
-#' @param field character. The name of a column in `sf`,
+#' @param field character (or numeric vector). The name of a column in `sf`,
 #' providing a value for each of the polygons rasterized. If NULL (default),
-#' all polygons will be given a value of 1.
+#' all polygons will be given a value of 1.  If a numeric vector this value
+#' will be used as the value given to the pixel.   (No recyling is done). 
 #' @param fun character. The name of a function by which to combine overlapping
 #' polygons. Currently takes "sum", "first", "last", "min", "max", "count", or
 #' "any".  Future versions may include more functions or the ability to pass
@@ -61,18 +62,32 @@ make_sf <- function(x, attr = NULL) {
 #' @export
 fasterize <- function(sf, raster, field = NULL, fun = "last", background = NA_real_, by = NULL) {
   
+    ## check the types up here
+  types <- wk::wk_meta(sf)$geometry_type
+  bad <- ! types %in% c(3, 6)
+
   ## ok so we get geometry from anything wk can handle
   geom <- wk::wk_handle(sf, wk::sfc_writer())
   
+  if (any(bad)) {
+    if (all(bad)) stop("no polygon geometries to fasterize")
+    geom <- geom[!bad, ] 
+    message(sprintf("removing %i geometries that are not polygon or multipolygon equivalent", sum(bad)))
+  }
   
+
   sf1 <- make_sf(geom)
-  if (inherits(sf, "data.frame") && !is.null(field)) {
-    sf1[[field]] <- sf[[field]]
+  if ( !is.null(field)) {
+    if (length(field) == 1L) {
+      sf1[[field]] <- sf[[field]]
+    } else if (length(field) == dim(sf1)[1L]) {
+      sf1[["field"]] <- field
+      field <- "field"
+    }
   }
   if (inherits(sf, "data.frame") && !is.null(by)) {
     sf1[[by]] <- sf[[by]]
   }
-  
   fasterize_cpp(sf1, raster, field, fun, background, by)
 }
 
diff --git a/man/fasterize.Rd b/man/fasterize.Rd
index 16e4afa..4c457bd 100644
--- a/man/fasterize.Rd
+++ b/man/fasterize.Rd
@@ -22,9 +22,10 @@ Can be created with \code{\link[raster:raster]{raster::raster()}}.
 The fasterize package provides a method to create a raster object from
 an polygon dataset.}
 
-\item{field}{character. The name of a column in \code{sf},
+\item{field}{character (or numeric vector). The name of a column in \code{sf},
 providing a value for each of the polygons rasterized. If NULL (default),
-all polygons will be given a value of 1.}
+all polygons will be given a value of 1.  If a numeric vector this value
+will be used as the value given to the pixel.   (No recyling is done).}
 
 \item{fun}{character. The name of a function by which to combine overlapping
 polygons. Currently takes "sum", "first", "last", "min", "max", "count", or
diff --git a/src/check_inputs.cpp b/src/check_inputs.cpp
index 6a1d6a9..cb5e95e 100644
--- a/src/check_inputs.cpp
+++ b/src/check_inputs.cpp
@@ -20,7 +20,7 @@ void check_inputs(Rcpp::DataFrame &sf,
   polygons = sf[Rcpp::as<std::string>(sf.attr("sf_column"))];
 
   if(!(Rf_inherits(polygons, "sfc_MULTIPOLYGON") |
-       Rf_inherits(polygons, "sfc_POLYGON"))) {
+       Rf_inherits(polygons, "sfc_POLYGON") | Rf_inherits(polygons, "sfc_GEOMETRY"))) {
     err_msg << "sf geometry must be POLYGON or MULTIPOLYGON" << std::endl;
   }
 
diff --git a/tests/testthat/test-01-inputcheck.R b/tests/testthat/test-01-inputcheck.R
index 3565bde..d82a5b0 100644
--- a/tests/testthat/test-01-inputcheck.R
+++ b/tests/testthat/test-01-inputcheck.R
@@ -34,13 +34,15 @@ test_that("fasterize needs polygons", {
                  geometry = st_sfc(lapply(list(p1, p2, p3),
                                           function(x) st_linestring(x[[1]]))))
   expect_error(fasterize(lines, r1),
-               "sf geometry must be POLYGON or MULTIPOLYGON")
+               "no polygon geometries to fasterize")
   
     lines_wkb <- data.frame(value = c(1,2,3),
                  geometry = wk::as_wkb(sf::st_cast(pols$geometry, "MULTILINESTRING")))
 
       expect_error(fasterize(lines_wkb, r1),
-               "geometry must be POLYGON or MULTIPOLYGON")
+               "no polygon geometries to fasterize")
+      
+      
 
 })
 
diff --git a/tests/testthat/test-05-by.R b/tests/testthat/test-05-by.R
index 738d84f..245d289 100644
--- a/tests/testthat/test-05-by.R
+++ b/tests/testthat/test-05-by.R
@@ -24,9 +24,10 @@ test_that("'by' argument works", {
 
 test_that("'by' layers are equivalent to layers generated separately", {
   rba <- fasterize(pols, r1, field="value", fun="sum", by ="value")
-  for(i in nrow(pols))
+  for(i in 1:nrow(pols)) {
   expect_equal(as.raster(rba[[i]]),
                as.raster(fasterize(pols[i,], r1, field="value", fun="sum")))
+  }
 })
 
 test_that("'by' can handle non-character fields", {