[PROJ] [PROJ 6.0.0] proj_create_operation_factory_context behavior

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

[PROJ] [PROJ 6.0.0] proj_create_operation_factory_context behavior

Didier Richard
Hi all,

While testing the library, the creation of a transformation between two specific CRS leads me facing 2 challenges :

1.- Despite the fact that the two CRS (Réunion island and French Antilles) have disjoint areas an operation is created.
The documentation expressed that default behavior for areas is "Strict containment", I, then, expected to have 0 operations in the end ...

If I set acc to 1.0, then, I got the right answer because the Ballpark transformation is removed.

2.- On the latter point, when acc equals 0.0, the candidate operation is pipeline containing a Ballpark transformation, proj_coordoperation_has_ballpark_transformation() still returns false ...

Any thoughts ?


The code :

#include <stdio.h>
#include <string.h>
#include "proj.h"

int main ( int argc, char *argv[] ) {
    PJ_CONTEXT *c;
    PJ *src, *tgt;
    PJ_PROJ_INFO info;
    PJ_OPERATION_FACTORY_CONTEXT *factory;
    PJ_OBJ_LIST *results;
    double acc = 0.0;

    src = proj_create(c, "IGNF:REUN47GAUSSL");  // area : 55.17,-21.42,55.92,-20.76
    tgt = proj_create(c, "IGNF:RGAF09UTM20");     // area : -63.2,14.25,-60.73,18.2
    // areas are strictly disjoint ... intersection is then empty
    factory = proj_create_operation_factory_context(c,NULL);
    if (factory == NULL) {
        fprintf(stderr,"Error : %s\n", proj_errno_string(proj_context_errno(c)));
        return 1;
    }
    results = proj_create_operations(c, src, tgt, factory);
    if (results == NULL) {
        fprintf(stderr,"No operation between '%s' and '%s'\n", proj_get_name(src), proj_get_name(tgt));
    } else {
        int i, n;
        PJ *ope;

        n = proj_list_get_count(results);
        fprintf(stderr,"%d operation(s) found :\n", n);
        for (i = 0; i < n ; i++) {
            ope = proj_list_get(c, results, i);
            info = proj_pj_info(ope);
            fprintf(stderr,"Info :\nID:%s\nDesc:%s\nDef:%s\nInv:%d\nAcc:%f\n", info.id, info.description, info.definition, info.has_inverse, info.accuracy);
            fprintf(stderr,"operation does %shave ballpark\n", proj_coordoperation_has_ballpark_transformation(c, ope)? "":"not ");
            if (strstr(proj_get_name(ope), "Ballpark") != NULL) {
                fprintf(stderr,"operation does have ballpark in its name !!!!\n");
            }
            fprintf(stderr,"'%s'\n", proj_get_name(ope));
            proj_destroy(ope);
        }
        proj_list_destroy(results);
    }

    proj_operation_factory_context_destroy(factory);
    proj_destroy(src);
    proj_destroy(tgt);
    proj_context_destroy(c); /* may be omitted in the single threaded case */
    return 0;
}

The output:

1 operation(s) found :
Info :
ID:pipeline
Desc:Inverse of GAUSS LABORDE REUNION + Ballpark geographic offset from Reunion Piton des Neiges geographiques (dms) to RGAF09 geographiques (dms) + UTM NORD FUSEAU 20
Def:proj=pipeline step inv proj=gstmerc lat_0=-21.1166666667 lon_0=55.5333333333 k_0=1 x_0=160000 y_0=50000 ellps=intl step proj=utm zone=20 ellps=GRS80
Inv:1
Acc:-1.000000
operation does not have ballpark
operation does have ballpark in its name !!!!
'Inverse of GAUSS LABORDE REUNION + Ballpark geographic offset from Reunion Piton des Neiges geographiques (dms) to RGAF09 geographiques (dms) + UTM NORD FUSEAU 20'

Regards,
--
RICHARD Didier - Chef du Centre de Compétences Technologies des Systèmes d'Information
http://fr.linkedin.com/pub/didier-richard/98/2a3/a8/ - https://www.osgeo.org/member/didier/
IGN/Direction des Sciences et Technologies de l'Information/ENSG Géomatique
6/8 avenue Blaise Pascal - BP Champs-sur-Marne - 77455 MARNE-LA-VALLÉE CEDEX 2
Tél : +33 (0) 1 43 98 83 23

_______________________________________________
PROJ mailing list
[hidden email]
https://lists.osgeo.org/mailman/listinfo/proj
Reply | Threaded
Open this post in threaded view
|

Re: [PROJ 6.0.0] proj_create_operation_factory_context behavior

Even Rouault-2
Hi Didier,

> 1.- Despite the fact that the two CRS (Réunion island and French Antilles)
> have disjoint areas an operation is created. The documentation expressed
> that default behavior for areas is "Strict containment", I, then, expected
> to have 0 operations in the end ...

Ah, I was hoping nobody would seriously try to check how all those criteria
exactly work :-) The logic is convoluted, somewhat arbitrary and has been
modified many times to try to "make things work". That is to say: return meaningful results
when possible, make sure existing regressions tests we had still pass,
and no being too pedantic (many people want to be able to do by default
meaningless transformations such as the one you exhibit, hence this concept of
ballpark transformation when we lack information to do datum shifts, etc).

The proj_operation_factory_context_set_spatial_criterion() defines how to compare
the area of use of a candidate coordinate operation with a representative area
of use of the source and target CRS. How that "representive area of use" is computed
is controlled by proj_operation_factory_context_set_crs_extent_use().
This one defaults to PJ_CRS_EXTENT_SMALLEST
That is, given the source CRS and target CRS, we only consider the extent of the
smallest one of those two, when we check the compatibility of coordinate operations
with the CRS area of use. In your case, this will be Réunion. The ballpark transformation
has worldwide coverage, so la Réunion is strictly contained in it,
hence the result you get.

If for example you set set_crs_extent_use() to PJ_CRS_EXTENT_INTERSECTION,
combined with the fix I just pushed per
https://github.com/OSGeo/proj.4/commit/b4a9e65cec051ca3cb16b8cccfa012d70ce10570 ,
then you'll get an empty set.

$ src/projinfo -s IGNF:REUN47GAUSSL -t IGNF:RGAF09UTM20 --crs-extent-use intersection
Candidate operations found: 0

That said PJ_CRS_EXTENT_INTERSECTION is not always the best answer.
For non-ballpark transformations, PJ_CRS_EXTENT_BOTH would be the most pedantic option
because it will return only coordinate operations whose area of use contains at least the
area of use of the source tand target CRS.

The reason for PJ_CRS_EXTENT_SMALLEST being the default is when doing transformation
from a ProjectedCRS with nation extent to WGS84 typically. In the database you'll get
possibly Helmert-based/grid-based transformation for that, whose area of use is the area
of use of the ProjectedCRS. So PJ_CRS_EXTENT_BOTH cannot be used there (because the
transformation is not valid for the whole world.

>
> 2.- On the latter point, when acc equals 0.0, the candidate operation is
> pipeline containing a Ballpark transformation,
> proj_coordoperation_has_ballpark_transformation() still returns false ...

Good catch. Was indeed a bug. Just fixed per
https://github.com/OSGeo/proj.4/commit/cca27b1fae234a90df42ff5341121759846dc39b

$ src/projinfo -s IGNF:REUN47GAUSSL -t IGNF:RGAF09UTM20 --summary
Candidate operations found: 1
unknown id, [...], unknown accuracy, World, ---> has ballpark transformation <----

Even

--
Spatialys - Geospatial professional services
http://www.spatialys.com
_______________________________________________
PROJ mailing list
[hidden email]
https://lists.osgeo.org/mailman/listinfo/proj
Reply | Threaded
Open this post in threaded view
|

Re: [PROJ 6.0.0] proj_create_operation_factory_context behavior

Didier Richard
Hi Even,

Thanks for the reply full of informations !
(I thought you were on leave ?-)

I usually check whether the source and target CRS areas intersects before transforming coordinates from one to the other because the underlaying geographic CRS have the same area as the projected one.

I will wait for the fixes (I guess in 6.1.0) to check these points (see https://github.com/dgricci/golang-proj for the reasons why I am testing the library :)

Best regards,
--
RICHARD Didier - Chef du Centre de Compétences Technologies des Systèmes d'Information
http://fr.linkedin.com/pub/didier-richard/98/2a3/a8/ - https://www.osgeo.org/member/didier/
IGN/Direction des Sciences et Technologies de l'Information/ENSG Géomatique
6/8 avenue Blaise Pascal - BP Champs-sur-Marne - 77455 MARNE-LA-VALLÉE CEDEX 2
Tél : +33 (0) 1 43 98 83 23


________________________________________
De : Even Rouault [[hidden email]]
Envoyé : mardi 30 avril 2019 15:16
À : [hidden email]
Cc : Didier Richard
Objet : Re: [PROJ] [PROJ 6.0.0] proj_create_operation_factory_context behavior

Hi Didier,

> 1.- Despite the fact that the two CRS (Réunion island and French Antilles)
> have disjoint areas an operation is created. The documentation expressed
> that default behavior for areas is "Strict containment", I, then, expected
> to have 0 operations in the end ...

Ah, I was hoping nobody would seriously try to check how all those criteria
exactly work :-) The logic is convoluted, somewhat arbitrary and has been
modified many times to try to "make things work". That is to say: return meaningful results
when possible, make sure existing regressions tests we had still pass,
and no being too pedantic (many people want to be able to do by default
meaningless transformations such as the one you exhibit, hence this concept of
ballpark transformation when we lack information to do datum shifts, etc).

The proj_operation_factory_context_set_spatial_criterion() defines how to compare
the area of use of a candidate coordinate operation with a representative area
of use of the source and target CRS. How that "representive area of use" is computed
is controlled by proj_operation_factory_context_set_crs_extent_use().
This one defaults to PJ_CRS_EXTENT_SMALLEST
That is, given the source CRS and target CRS, we only consider the extent of the
smallest one of those two, when we check the compatibility of coordinate operations
with the CRS area of use. In your case, this will be Réunion. The ballpark transformation
has worldwide coverage, so la Réunion is strictly contained in it,
hence the result you get.

If for example you set set_crs_extent_use() to PJ_CRS_EXTENT_INTERSECTION,
combined with the fix I just pushed per
https://github.com/OSGeo/proj.4/commit/b4a9e65cec051ca3cb16b8cccfa012d70ce10570 ,
then you'll get an empty set.

$ src/projinfo -s IGNF:REUN47GAUSSL -t IGNF:RGAF09UTM20 --crs-extent-use intersection
Candidate operations found: 0

That said PJ_CRS_EXTENT_INTERSECTION is not always the best answer.
For non-ballpark transformations, PJ_CRS_EXTENT_BOTH would be the most pedantic option
because it will return only coordinate operations whose area of use contains at least the
area of use of the source tand target CRS.

The reason for PJ_CRS_EXTENT_SMALLEST being the default is when doing transformation
from a ProjectedCRS with nation extent to WGS84 typically. In the database you'll get
possibly Helmert-based/grid-based transformation for that, whose area of use is the area
of use of the ProjectedCRS. So PJ_CRS_EXTENT_BOTH cannot be used there (because the
transformation is not valid for the whole world.

>
> 2.- On the latter point, when acc equals 0.0, the candidate operation is
> pipeline containing a Ballpark transformation,
> proj_coordoperation_has_ballpark_transformation() still returns false ...

Good catch. Was indeed a bug. Just fixed per
https://github.com/OSGeo/proj.4/commit/cca27b1fae234a90df42ff5341121759846dc39b

$ src/projinfo -s IGNF:REUN47GAUSSL -t IGNF:RGAF09UTM20 --summary
Candidate operations found: 1
unknown id, [...], unknown accuracy, World, ---> has ballpark transformation <----

Even

--
Spatialys - Geospatial professional services
http://www.spatialys.com
_______________________________________________
PROJ mailing list
[hidden email]
https://lists.osgeo.org/mailman/listinfo/proj