r-spatial / RQGIS3

GNU Lesser General Public License v3.0
69 stars 19 forks source link

Ignore invalid geometries #11

Open daarizap opened 5 years ago

daarizap commented 5 years ago

Hi, I have been running the clip command from QGIS in R using RQGIS3 package. Everything goes fine except when I use as the input layer a vector with some invalid geometries. QGIS can be set to ignore such invalid geometries and still perform the clipping (or any other action) but in RQGIS3 I get the following error:

Error in py_call_impl(callable, dots$args, dots$keywords) : QgsProcessingException: There were errors executing the algorithm.

I don't send info about the R session as this is not caused by the code (which works well when I use another input vector with no invalid geometries). So my question is more about whether there is an option to run the clipping command (or any other command) using RQGIS3 and set it to ignore the invalid geometries and still perform the clipping. (I could not find information about this in the package documentation). In QGIS this can be done by just adjusting the configurations.

Fixing the geometry of the vector is not an option. I have already tried this.

jannes-m commented 5 years ago

Could you please provide a reproducible example? Otherwise it is hard to tell what possibly went wrong.

daarizap commented 5 years ago

Here is a reproducible example:

=============

library("rgdal") library("raster") library("RQGIS3")

set_env() params = get_args_man(alg = "native:clip") a<-#directory with the files params$INPUT = file.path(a, "1.shp") params$OVERLAY = file.path (a, "2.shp") params$OUTPUT = file.path (a, "3.shp") out = run_qgis(alg = "native:clip", params = params, load_output = FALSE)

====

output Error in py_call_impl(callable, dots$args, dots$keywords) : QgsProcessingException: There were errors executing the algorithm.

===============

Here is a link for the files used in the example: https://we.tl/t-hIFKmqEi94

I already know the issue is that the INPUT file has invalid geometries, but in QGIS this can be ignored and clipping can be done. So my question is more about whether this can also be ignored in RQGIS3?

Info of the session

R v. 3.6.0 (2019-04-26) Rstuido 1.2.1335 Windowds 10 v. 1803 RQGIS3 v. 1.0.1.9000 rgdal v. 1.4.3 raster v. 2.9.5 QGIS ltr v. 3.4.8-Madeira

jannes-m commented 5 years ago

A reproducible example should not make use of a file which is of size 1.5GB. Looking at the available parameters of native:clip, I don't see how you could tell QGIS3 to ignore invalid geometries. How would you do so in the GUI? Maybe you could also use grass7:v.overlay since GRASS cleans geometries before doing any processing. However, this might take a while because internally QGIS3 would send the files to GRASS7 and after the processing GRASS7 would have to export the files to QGIS3.

daarizap commented 5 years ago

Sorry I could not send another file, that is the only one I am using that has invalid geometries (I tried looking for alternative files online but I couldn't find any with invalid geometries).

In QGIS you do Settings -> Options -> Processing tab, expand out the General setting -> Invalid feature filtering -> Ignore features with invalid geometries.

I'll try with grass from RQGIS3, but I have already tried cleaning the geometries directly with grass before and it didn't work (the file has a lot of them) so I have to find ways to work with these invalid geometries.

jannes-m commented 5 years ago

Ah ok, thanks for reporting back. I will have a look at how one can use invalid geometries using the Python API.

jannes-m commented 5 years ago

I have found an answer how to use invalid geometries using the QGIS3 Python API, see here. However, I have not tested it. Can you try this code, please?

library("RQGIS3")
alg = "native:clip"
# construct a parameter-argument list using get_args_man and user input
params = get_args_man(alg = alg)
# PLEASE SPECIFY YOUR PARAMETERS!!!
params$INPUT = ""
params$OVERLAY = ""
params$OUTPUT = ""

# convert R parameter-argument list into a Python dictionary
params = r_to_py(params)

# accept invalid geometries
# Python syntax
# context = dataobjects.createContext()
# context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck)
# and doing the same with reticulate
context = py$processing$tools$dataobjects$createContext()
context$setInvalidGeometryCheck(py$QgsFeatureRequest$GeometryNoCheck)

# run QGIS
msg = py_capture_output(expr = {
  res =
    py$processing$run(algOrName = alg, parameters = params,
                      feedback = py$QgsProcessingFeedback(), context = context)
})

If it works we can think about implementing it in RQGIS3.