Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: [[[<-,SpatVector] cannot add these values after erase() with specific geometries in a specific order #1710

Closed
erkent-carb opened this issue Jan 17, 2025 · 2 comments

Comments

@erkent-carb
Copy link

I originally asked the question on stackoverflow here and in my testing since think it is possibly related to erase(). Thanks for your helpful advice on figuring out where the issue happens.

I have a SpatVect (this_weight) which I then erase parts from using two other SpatVects (I will call these masks 1 and 2). After the second erase() call, I am unable to add a new column (Error: [[[<-,SpatVector] cannot add these values), plot it, or use writeVector() to save it (Error: basic_string::_M_create). In the course of testing this I found that if I only used one mask, or if I reversed the order of the masking (i.e., erase mask 2 first and then mask 1) then I did not get these errors. It seems it is possibly an issue with my specific geometries, though they appear valid. The reprex below shows first the original ordering test (errors) and the reverse order test (no errors). The attached zip file contains the three necessary shapefiles used.

Any help figuring out if it is just these geometries or a bug are appreciated.

bug_testing_2025-01-16.zip

library(terra)
library(ggplot2)

io_dir <- "C:/Users/ekent/Desktop/bug_testing_2025-01-16/"

#################################################################################################################################################
# I get the error when running this code

# the SpatVect I am working with (a subset of another file obtained using query() with the filter argument)
this_weight <- vect(file.path(io_dir,"this_weight_original.shp"))
nrow(weight)
this_weight$test <- 1:nrow(this_weight)

# first mask
mask1 <- terra::vect(file.path(io_dir,"this_protected_lands_mask.shp"))
# now project the mask features to the crs of the weight file
mask1_projected <- terra::project(mask1, this_weight)
mask1_projected_valid <-  terra::makeValid(mask1_projected)

# erase the parts of the weight file features that fall inside the first mask
this_weight <- terra::erase(this_weight, mask1_projected_valid)
nrow(this_weight)
# adding new column here okay
this_weight$test2 <- 1:nrow(this_weight)

# geometry seems valid
any(!is.valid(this_weight))

# writing to file succeeds here
writeVector(this_weight, filename = file.path(io_dir,"this_weight_after_protected_lands_applied4.shp"))

# Plotting succeeds here
ggplot()+
  theme_bw() +
  geom_spatvector(data = this_weight)

# second mask
mask2 <- terra::vect(file.path(io_dir,"this_coast_mask2.shp"))
# now project the mask features to the crs of the weight file
mask2_projected <- terra::project(mask2, this_weight)
mask2_projected_valid <-  terra::makeValid(mask2_projected)

# erase the parts of the weight file features that fall inside the second mask
this_weight <- terra::erase(this_weight, mask2_projected_valid) # this line appears to be where things go wrong, though we don't get an error here
nrow(this_weight)

# geometry seems valid
any(!is.valid(this_weight))

# when trying to write at this point I get:
# Error: basic_string::_M_create
writeVector(this_weight, filename = file.path(io_dir,"this_weight_after_protected_lands_and_coast_applied4.shp"))

# I am also not able to plot after the last erase()
# Error in `$<-.data.frame`(`*tmp*`, geometry, value = c("010600000.........
ggplot()+
  theme_bw() +
  geom_spatvector(data = this_weight)

# this is the line when we have the original error: Error: [[[<-,SpatVector] cannot add these values
this_weight$test3 <- 1:nrow(this_weight)


#################################################################################################################################################
# if I reverse the order the masks are applied, I don't get the error anymore

# the SpatVect I am working with (a subset of another file obtained using query() with the filter argument)
this_weight <- vect(file.path(io_dir,"this_weight_original.shp"))
nrow(weight)
this_weight$test <- 1:nrow(this_weight)

# second mask (this time applied first)
mask2 <- terra::vect(file.path(io_dir,"this_coast_mask2.shp"))
# now project the mask features to the crs of the weight file
mask2_projected <- terra::project(mask2, this_weight)
mask2_projected_valid <-  terra::makeValid(mask2_projected)

# erase the parts of the weight file features that fall inside the second mask
this_weight <- terra::erase(this_weight, mask2_projected_valid) # this line appears to be where things go wrong, though we don't get an error here
nrow(this_weight)

# geometry seems valid
any(!is.valid(this_weight))

# writes fine
writeVector(this_weight, filename = file.path(io_dir,"this_weight_after_protected_lands_and_coast_applied5.shp"))

# plots fine
ggplot()+
  theme_bw() +
  geom_spatvector(data = this_weight)

# this is the line when we had the original error, but not in this order
this_weight$test3 <- 1:nrow(this_weight)

# first mask
mask1 <- terra::vect(file.path(io_dir,"this_protected_lands_mask.shp"))
# now project the mask features to the crs of the weight file
mask1_projected <- terra::project(mask1, this_weight)
mask1_projected_valid <-  terra::makeValid(mask1_projected)

# erase the parts of the weight file features that fall inside the first mask
this_weight <- terra::erase(this_weight, mask1_projected_valid)
nrow(this_weight)
# adding new column here okay
this_weight$test2 <- 1:nrow(this_weight)

# geometry seems valid
any(!is.valid(this_weight))

# writing to file succeeds here
writeVector(this_weight, filename = file.path(io_dir,"this_weight_after_protected_lands_applied6.shp"))

# Plotting succeeds here
ggplot()+
  theme_bw() +
  geom_spatvector(data = this_weight)



@rhijmans
Copy link
Member

Thank you. I believe this has now been fixed. At least your example now works:

library(terra)
w1 <- vect("this_weight_original.shp")
m1 <- terra::vect("this_protected_lands_mask.shp")
m2 <- terra::vect("this_coast_mask2.shp")

m1v <- terra::project(m1, w1) |> terra::makeValid()
m2v <- terra::project(m2, w1) |> terra::makeValid() |> crop(ext(w1) + 10000)
values(w1) <- data.frame(w1=1:nrow(w1))

w2 <- terra::erase(w1, m1v)
w2$w2 <- 1:nrow(w2)
w3 <- terra::erase(w2, m2v) 
w3$w3 <- 1:nrow(w3)
w3
# class       : SpatVector 
# geometry    : polygons 
# dimensions  : 193, 3  (geometries, attributes)
# extent      : -222827.4, -156509.7, 86497.14, 161041  (xmin, xmax, ymin, ymax)
# coord. ref. : MM5_sphere 
# names       :    w1    w2    w3
# type        : <int> <int> <int>
# values      :     1     1     1
#                   2     2     2
#                   3     3     3

@erkent-carb
Copy link
Author

Thanks very much. I confirmed that my example works now too.

netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this issue Feb 8, 2025
# Version 1.8-15

## Bug Fixes

- `Readrds` Failed For Rasters With Timestep="Seconds"
  [#1711](Https://github.com/Rspatial/terra/issues/1711) by Pascal
  Oettli

- `divide<SpatVector>` always returned NULL
  [#1724](rspatial/terra#1724) by Márcia
  Barbosa

- `erase` failed in some cases
  [#1710](rspatial/terra#1710) by
  erkent-carb

## enhancements

- `bestMatch` now has argument "fun" to allow the use of different
  distance measures, and a <matrix> method

- `wrap` (and `writeRDS`) now captures varnames/longnames
  [#1719](rspatial/terra#1719) by Andrew
  Gene Brown

- improved raster metadata writing
  [#1714](rspatial/terra#1714) by Andrew Gene
  Brown

- `vect` and `writeVector` now properly read and write date and
  datetime
  data. [#1718](rspatial/terra#1718) by
  Andrew Gene Brown

- improved estimate of available memory on linux systems
  [#1506](rspatial/terra#1506) by Cedric
  Rossi

# version 1.8-10

Released 2025-01-13

## bug fixes

- `expanse<SpatRaster>(transform=TRUE)` crashed R when the crs was
  "local". [#1671](rspatial/terra#1671) by
  Michael Chirico

- `patches(values=TRUE)` wrapped around the edges
  [#1675](rspatial/terra#1675) by Michael
  Chirico

- `spin` now correctly handles spherical coordinates
  [#1576](rspatial/terra#1576) by jeanlobry

- `mosaic` sometimes crashed R
  [#1524](rspatial/terra#1524) by John
  Baums, Dave Klinges, and Hugh Graham.

- `spatSample` ignored argument "exp" when taking a random sample with
  na.rm=TRUE on a large raster
  [#1437](rspatial/terra#1437) by Babak
  Naimi

- `split<SpatVector,SpatVector>` did not work properly
  [#1619](rspatial/terra#1619) by Michael
  Sumner

- `autocor` improved handling of NA cells for global Moran computation
  [#1992](rspatial/terra#1592) by Nicholas
  Berryman

- `shade` is more
  memory-safe. [#1452](rspatial/terra#1452)
  by Francis van Oordt and Chris English

- fixed bug in `rasterize` revealed when using `crop(mask=TRUE)`
  [#1686](rspatial/terra#1686) by edixon1

- fixed `to_id = NA` bug in `nearest`
  [#1471](rspatial/terra#1471) by Mats
  Blomqvist

- better handling of date/unit
  [#1684](rspatial/terra#1684) and
  [#1688](rspatial/terra#1688) by Andrew
  Gene Brown

- `spatSample(method="regular")` on a raster with one column returned
  too many samples
  [#1362](rspatial/terra#1362) by Daniel R
  Schlaepfer


## enhancements

- `plot<SpatVector>` now uses the same default viridis color palette
  as `plot<SpatRaster>`
  [#1670](rspatial/terra#1670) by Márcia
  Barbosa

- `relate` now accepts relation="equals"
  [#1672](rspatial/terra#1672) by Krzysztof
  Dyba

- `init` now accepts additional arguments for function "fun"

- better handling of the 32 connections limitation set by the HDF4
  library [#1481](rspatial/terra#1481) by
  Dimitri Falk

- When using RStudio a once per session warning is given when using
  draw, sel or click
  [#1063](rspatial/terra#1063) by Sergei
  Kharchenko

- `distance<SpatRaster>` from lon and lat lines/polygons computes
  distance to the edges instead of the nodes
  [#1462](rspatial/terra#1462) by Derek
  Friend

- `distance<SpatVector,SpatVector>` now works for lon/lat data
  [#1615](rspatial/terra#1615) by Wencheng
  Lau-Medrano

- using overviews for faster plotting of COGs over http
  [#1353](rspatial/terra#1353) by Michael
  Sumner and [#1412](rspatial/terra#1412);
  and argument `plot(x, overview=)` to change the default behavior.

- `extract` with points is now faster for rasters accessed over http
  [#1504](rspatial/terra#1504) by Krzysztof
  Dyba

- `extract` with many points on very large rasters was slower in
  compared to doing the same with "raster" (which uses terra for
  that!) [#1584](rspatial/terra#1584) by
  Hassan Masoomi

- `merge` now has three alternative algorithms
  [1366](rspatial/terra#1366) by Hassan
  Masoomi and [#1650](rspatial/terra#1650)
  by Agustin Lobo


## new

- `$<SpatRaster>` can now be used to get a categorical SpatRaster with
  a different active category

- `scale_linear<SpatRaster>` method for linear scaling of cell values
  between a minimum and maximum value such as 0 and 1

- `distance` and related methods get argument "method" to choose the
  distance algorithm for lon/lat data
  [#1677](rspatial/terra#1677) by Márcia
  Barbosa

- `divide<SpatRaster>` and `divide<SpatVector>` methods

- `nseg` counts the number of segments in a SpatVector
  [#1647](rspatial/terra#1674) by Michael
  Chirico

- `extract` argument "search_radius" to extract values from the
  nearest raster cell that is not `NA`
  [#873](rspatial/terra#873) by
  matthewseanmarcus

- `combineLevels` to combine the levels of all layers
  [link](https://stackoverflow.com/questions/79340152/how-to-set-factor-levels-in-a-rast-stack-using-terra-when-different-levels-exi)
  on SO by Sam
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants