Skip to content

Commit

Permalink
feat: buffer() and settleGeom
Browse files Browse the repository at this point in the history
  • Loading branch information
jiajic committed Oct 28, 2024
1 parent f873c40 commit 7e5f179
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 5 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Collate:
'NN_network.R'
'aggregate.R'
'auxilliary.R'
'buffer.R'
'combine_metadata.R'
'slot_accessors.R'
'create.R'
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ exportMethods(as.sf)
exportMethods(as.sp)
exportMethods(as.stars)
exportMethods(as.terra)
exportMethods(buffer)
exportMethods(calculateOverlap)
exportMethods(centroids)
exportMethods(colnames)
Expand Down Expand Up @@ -351,6 +352,7 @@ exportMethods(relate)
exportMethods(rescale)
exportMethods(rownames)
exportMethods(setGiotto)
exportMethods(settleGeom)
exportMethods(shear)
exportMethods(snap)
exportMethods(spatIDs)
Expand Down Expand Up @@ -392,6 +394,7 @@ importMethodsFrom(terra,area)
importMethodsFrom(terra,as.data.frame)
importMethodsFrom(terra,as.points)
importMethodsFrom(terra,as.polygons)
importMethodsFrom(terra,buffer)
importMethodsFrom(terra,centroids)
importMethodsFrom(terra,convHull)
importMethodsFrom(terra,crop)
Expand Down
7 changes: 7 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@

# GiottoClass 0.4.1

## new
- `buffer()` for `giottoPolygon`, `giottoPoints`, `spatLocsObj`. Default is to crop by voronoi borders with `settleGeom()`
- `settleGeom()` for `giottoPolygon` and `SpatVector` for finding non overlapping borders determined by voronoi


# GiottoClass 0.4.0 (2024/10/27)

## breaking changes
Expand Down
120 changes: 120 additions & 0 deletions R/buffer.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#' @include generics.R
NULL

# Documentations ------------------------------------------------------------ #
#' @name buffer
#' @title Create a buffer around vector geometries
#' @description Calculate a buffer around all geometries of a `SpatVector`
#' @inheritParams terra::buffer
#' @param \dots additional params to pass
#' @param settle logical. Settle the borders between polygons by cutting them
#' where they touch based on voronoi boundaries.
#' @returns `giottoPolygon` of buffer polygons
#' @examples
#' sl <- GiottoData::loadSubObjectMini("spatLocsObj")
#' slb <- buffer(sl, 30)
#' plot(slb)
NULL

#' @name settleGeom
#' @title Settle polygon bounds
#' @description Settle the boundaries between polygons when they overlap by
#' splitting both at the point where they touch. Works through intersection
#' with the voronoi of the centroids.
#' @param x a `SpatVector` of type "polygons" or object inheriting from
#' `giottoPolygon`
#' @returns same class as `x`, with the contained polygons borders settled
#' in relation to each other.
#' @examples
#' svp <- GiottoData::loadSubObjectMini("giottoPolygon")[]
#' svp <- buffer(svp, 5)
#' plot(svp)
#' svp <- settleGeom(svp)
#' plot(svp)
NULL
# --------------------------------------------------------------------------- #




# buffer ####
#' @rdname buffer
#' @export
setMethod("buffer", "spatLocsObj", function(x, width, ..., settle = TRUE) {
x_use <- as.points(x)
res <- buffer(x = x_use, width = width, ...)
if (settle) res <- settleGeom(res)
gpoly <- createGiottoPolygon(res, verbose = FALSE)
return(gpoly)
})

#' @rdname buffer
#' @export
setMethod("buffer", signature("giottoPoints"), function(x, width, ..., settle = TRUE) {
x_use <- x[]
res <- buffer(x = x_use, width = width, ...)
if (settle) res <- settleGeom(res)
res$poly_ID <- sprintf("poly_", seq_len(nrow(res)))
gpoly <- createGiottoPolygon(res, verbose = FALSE)
return(gpoly)
})

#' @rdname buffer
#' @export
setMethod("buffer", signature("giottoPolygon"), function(x, width, ..., settle = TRUE) {
x_use <- x[]
res <- buffer(x = x_use, width = width, ...)
if (settle) res <- settleGeom(res)
x[] <- res
return(x)
})


# settleGeom ####

#' @rdname settleGeom
#' @export
setMethod("settleGeom", signature("giottoPolygon"), function(x) {
x[] <- settleGeom(x[])
})

#' @rdname settleGeom
#' @export
setMethod("settleGeom", signature("SpatVector"), function(x) {
if (!terra::geomtype(x) == "polygons") {
stop("`settleGeom()` can only be used with polygon geometries")
}

orig_names <- names(x)
# apply index
x$.idx <- seq_len(nrow(x))
names_keep <- c(orig_names, ".idx")

# Find overlapping circles
overlaps <- relate(x, relation = "overlaps", pairs = TRUE) |>
as.vector() |>
unique()
if(length(overlaps) == 0L) return(x) # If no overlaps, return original polys

# Create Voronoi polygons for the points
# Note: extend parameter ensures Voronoi polygons cover all buffer areas
vor <- voronoi(centroids(x), bnd = ext(x) * 1.2)
# voronoi does not return values in order. Reorder with index
vor <- terra::sort(vor, v = ".idx")

# Process each buffer
reslist <- lapply(overlaps, function(i) {
terra::intersect(vor[i], x[i])
})

res <- do.call(rbind, reslist)
names(res)[seq_along(names_keep)] <- names_keep
res <- res[, names_keep] # drop extra fields from intersect
x <- x[-res$.idx] # drop polys to edit
x <- rbind(x, res)
x <- terra::sort(x, v = ".idx")
x <- x[, orig_names]

return(x)
})

1 change: 1 addition & 0 deletions R/generics.R
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ setGeneric("affine", function(x, y, ...) standardGeneric("affine"))
setGeneric("shear", function(x, ...) standardGeneric("shear"))
setGeneric("XY", function(x, ...) standardGeneric("XY"))
setGeneric("XY<-", function(x, ..., value) standardGeneric("XY<-"))
setGeneric("settleGeom", function(x, ...) standardGeneric("settleGeom"))
if (!isGeneric("area")) {
setGeneric("area", function(x, ...) standardGeneric("area"))
}
Expand Down
7 changes: 2 additions & 5 deletions R/package_imports.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,14 @@
#' @importFrom methods slotNames
#' @importFrom methods validObject
#' @importFrom graphics legend par rect
#' @importMethodsFrom terra spin
#' @importMethodsFrom terra flip
#' @importMethodsFrom terra rescale
#' @importMethodsFrom terra spin flip rescale t
#' @importMethodsFrom Matrix t
#' @importMethodsFrom terra t
#' @importMethodsFrom terra ext ext<- convHull minCircle minRect
#' @importMethodsFrom terra plot
#' @importMethodsFrom terra wrap
#' @importMethodsFrom terra zoom
#' @importMethodsFrom terra crop
#' @importMethodsFrom terra vect
#' @importMethodsFrom terra vect buffer
#' @importMethodsFrom terra relate
#' @importMethodsFrom terra union erase intersect symdif snap
#' @importMethodsFrom terra as.data.frame as.polygons as.points
Expand Down
36 changes: 36 additions & 0 deletions man/buffer.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions man/settleGeom.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 7e5f179

Please sign in to comment.