[R-sig-Geo] cannot apply a gridded transformation with sf

Roger Bivand Roger@B|v@nd @end|ng |rom nhh@no
Tue Oct 12 17:25:37 CEST 2021


One basic problem is that a regression was introduced in PROJ from 7.2.0, 
resolved last week by https://github.com/OSGeo/PROJ/pull/2884, where grid 
transformations ceased to work if the prime meridian was not Greenwich. So 
for PROJ 7.2.0-8.1.1, the closest you can get is:

ptSf_2154_via_CRS84 <- st_transform(st_transform(ptSf_27572, 
crs="OGC:CRS84"), crs=2154)
st_distance(ptSf_2154_via_CRS84, ptSf_2154)
# Units: [m]
#          [,1]
# [1,] 3.777444

through a CRS84 hub using a Helmert transformation, unless you can force 
the pipeline as shown in the sf issue: 
https://github.com/r-spatial/sf/issues/1815
This forcing so far only works on Linux, as the user-writable directory is 
not properly accessed in sf for Windows or macOS yet. You may also use the 
rgdal work-around setting the user-writable directory as shown earlier in 
this thread.

Roger

On Mon, 11 Oct 2021, Roger Bivand wrote:

> Assuming the Windows CRAN binary. Binary sf (and rgdal) packages bundle PROJ 
> and GDAL metadata files taken as fixed for given releases of PROJ and GDAL, 
> but from PROJ 7, a content download network (CDN, https://cdn.proj-org) is 
> also available. Binary packages set the PROJ_LIB environment variable when 
> loaded to the bundled metadata. From PROJ 7, a separate user-writable 
> directory is also needed to cache transformation grids downloaded from the 
> CDN.
>
> The current difficulty stems both from problems passing through the string 
> defining the user-writable directory, and from st_transform() (and 
> rgdal::spTransform()) not choosing the most accurate transformation pipeline 
> (possibly because the user-writable directory is not properly detected ??). 
> The following code works around the problem by coercing the sf object to a 
> Spatial object from sp, using spTransform() instead of st_transform, then 
> coercing back to sf. spTransform() does not use PROJ through GDAL, but uses 
> PROJ directly; it still needs to be told which transformation pipeline to 
> use.
>
> #  at the very beginning of the R session, define the user-writable directory
> td <- tempfile()
> dir.create(td)
> Sys.setenv("PROJ_USER_WRITABLE_DIRECTORY"=td)
> library(rgdal)
> rgdal_extSoftVersion()
> #  check the PROJ search paths and check that the user-writable directory is 
> #  empty and that the CDN is not enabled
> (pths <- get_proj_search_paths())
> list.files(pths[1])
> is_proj_CDN_enabled()
> # define the objects and check that the search paths are still OK
> library(sf)
> get_proj_search_paths()
> pt_27572 <- data.frame(X=55824.4970,Y=2394454.2120)
> pt_2154 <- data.frame(X=107242.8310,Y=6832277.1820)
> ptSf_27572 <- st_as_sf(pt_27572, coords = c("X", "Y"), crs=27572)
> ptSf_2154 <- st_as_sf(pt_2154, coords = c("X", "Y"), crs=2154)
> # enable the CDN and that the user-writable directory is still empty
> enable_proj_CDN()
> is_proj_CDN_enabled()
> list.files(pths[1])
> # list candidate coordinate operations
> (o <- list_coordOps("EPSG:27572", "EPSG:2154"))
> # transform using the first returned coordinate operation pipeline
> ptSf_2154_grid <- st_as_sf(spTransform(as(ptSf_27572, "Spatial"),
>  CRS("EPSG:2154"), coordOp=o[1, "definition"]))
> # print the coordinate operation used
> get_last_coordOp()
> # check that the user-writable directory is populated
> list.files(pths[1])
> # check distance to defined point in target crs
> st_distance(ptSf_2154_grid, ptSf_2154)
>
> With PROJ 7.2.1 this yields a different sub-millimetre distance from PROJ 
> 8.1.1, because a different grid is preferred, but both do transform your 
> input point to your expected output point if half a millimetre is close 
> enough.
>
> I've raised https://github.com/r-spatial/sf/issues/1815 with some more 
> details. This may take some time to resolve satisfactorily.
>
> Roger
>
> On Mon, 11 Oct 2021, Roger Bivand wrote:
>
>>  Dear Jean-Luc,
>>
>>  Thanks for a very helpful report. I'll answer fully later, but if you
>>  could provide in addition your platform (I think Windows or macOS, sf
>>  installed as a CRAN binary), that would help. On these platforms, access
>>  to the CDN for grids is not what it should be, and your example is helping
>>  debug the problem.
>>
>>  Best wishes,
>>
>>  Roger
>>
>>  On Sun, 10 Oct 2021, Jean-Luc Dupouey wrote:
>>
>>>   Dear forumites,
>>>
>>>   I try to apply a gridded transformation of coordinates in |sf|, but it
>>>   does not work. Is there something else to do apart from calling
>>> |  sf_proj_network(TRUE)|? Here is the 7 lines of code I used:
>>> 
>>> |  pt_27572 <- data.frame(X=55824.4970,Y=2394454.2120)| # set coordinates
>>>   of one point in EPSG:27572
>>> 
>>> |  pt_2154 <- data.frame(X=107242.8310,Y=6832277.1820)| # known accurate
>>>   coordinates of the same point in EPSG:2154 (from calculations of the
>>>   French National Geographic Institute)
>>> 
>>> |  ptSf_27572 <- st_as_sf(pt_27572, coords = c("X", "Y"), crs = 27572)| #
>>>   build sf object
>>> 
>>> |  ptSf_2154 <- st_as_sf(pt_2154, coords = c("X", "Y"), crs = 2154)| #
>>>   build sf object
>>> 
>>> |  sf_proj_network(TRUE)| # allow search for online datum grids in the
>>>   PROJ CDN
>>>
>>>   [1] "https://cdn.proj.org"
>>> 
>>> |  sf_proj_pipelines("EPSG:27572", "EPSG:2154")| # grids
>>>   (fr_ign_gr3df97a.tif) seem to be found for accurate transformation from
>>>   EPSG:27572 to EPSG:2154
>>> 
>>> |  Candidate coordinate operations found: 3 Strict containment: FALSE Axis
>>>   order auth compl: FALSE Source: EPSG:27572 Target: EPSG:2154 Best
>>>   instantiable operation has accuracy: 1 m Description: Inverse of Lambert
>>>   zone II + NTF (Paris) to NTF (1) + NTF to RGF93 (1) + Lambert-93
>>>   Definition: +proj=pipeline +step +inv +proj=lcc +lat_1=46.8 +lat_0=46.8
>>>   +lon_0=0 +k_0=0.99987742 +x_0=600000 +y_0=2200000 +ellps=clrk80ign
>>>   +pm=paris +step +proj=push +v_3 +step +proj=cart +ellps=clrk80ign +step
>>>   +proj=xyzgridshift +grids=fr_ign_gr3df97a.tif +grid_ref=output_crs
>>>   +ellps=GRS80 +step +inv +proj=cart +ellps=GRS80 +step +proj=pop +v_3
>>>   +step +proj=lcc +lat_0=46.5 +lon_0=3 +lat_1=49 +lat_2=44 +x_0=700000
>>>   +y_0=6600000 +ellps=GRS80 |
>>> 
>>> |  ptSf_2154_grid <- st_transform(ptSf_27572,crs=2154)| # apply 
>>> |  transformation
>>> 
>>> |  st_distance(ptSf_2154_grid,ptSf_2154)| # incorrect (ungridded)
>>>   transformation, the distance should be zero. 3.777 m is the known error
>>>   for the ungridded transformation.
>>> 
>>> |  Units: [m] [,1] [1,] 3.777346 |
>>>
>>>   I read in (the so useful) "Spatial Data Science" that by default, the
>>>   most accurate pipeline is chosen by |st_transform|. Why isn't it the
>>>   case here?
>>>
>>>   I am running R version 4.1.1, GEOS 3.9.1, GDAL 3.2.1, PROJ 7.2.1.
>>>
>>>   Thanks for your help,
>>>
>>>   Jean-Luc
>>>
>>> 
>> 
>> 
>
>

-- 
Roger Bivand
Emeritus Professor
Department of Economics, Norwegian School of Economics,
Postboks 3490 Ytre Sandviken, 5045 Bergen, Norway.
e-mail: Roger.Bivand using nhh.no
https://orcid.org/0000-0003-2392-6140
https://scholar.google.no/citations?user=AWeghB0AAAAJ&hl=en



More information about the R-sig-Geo mailing list