MTES-MCT / metadata-postgresql

Plume : gestion des métadonnées du patrimoine PostgreSQL
https://mtes-mct.github.io/metadata-postgresql/
GNU Affero General Public License v3.0
1 stars 1 forks source link

Précision des coordonnées géographiques #31

Closed alhyss closed 2 years ago

alhyss commented 2 years ago

Par défaut, les méthodes asWkt et apparentées des classes de géométrie de QGIS encodent les coordonnées avec une précision de 17 décimales, tandis que la fonction ST_AsText de PostGIS en conserve jusqu'à 15 (en supprimant les zéros non significatifs). Comme souligné par @GilGuillouet, c'est certainement beaucoup trop d'une manière générale.

À titre de référence, quand nous avions été confronté au problème des 25 chiffres significatifs sur le CSW de GéoIDE, il avait été convenu de tronquer à 8 chiffres, ce qui correspond à une précision de l'ordre du millimètre pour les latitudes et pour les longitudes à l'équateur.

Il faudrait confirmer que c'est bien vrai pour toutes les méthodes QGIS que tu as utilisées pour générer les représentations WKT, @WREATCHED, mais qgis.core.QgsAbstractGeometry.asWkt admet un paramètre precision (valeur par défaut 17, donc), qui permettrait de réduire la précision. ST_AsText a également un paramètre maxdecimaldigits (valeur par défaut 15)... mais malheureusement seulement à partir de PostGIS 2.5, et je ne crois pas qu'on puisse considérer comme acquis que tous les serveurs PG10+ aient au moins cette version. En fait, j'ai connaissance d'au moins un serveur EOLE PG10 avec PostGIS 2.4, et ils pourraient bien être tous dans ce cas.

Quoi qu'il en soit, on pourrait définir un paramètre utilisateur wktMaxDecimalDigits[^nomparam], avec une valeur par défaut de 8, qui permettrait à l'utilisateur de modifier la précision des géométries qu'il trace ou calcule.

[^nomparam]: Ou wktPrecision, mais je trouve le nom du paramètre de PostGIS plus explicite, au moins on sait qu'il ne s'agit pas du nombre de chiffres total.

Ce paramètre utilisateur servirait de valeur pour l'argument precision (ou équivalent) des méthodes de génération de WKT de QGIS. Côté PostgreSQL, je peux sans difficulté modifier les méthodes plume.pg.queries.query_get_geom_centroid et plume.pg.queries.query_get_geom_extent pour appeler ST_AsText avec un paramètre supplémentaire. Le truc, c'est que PostgreSQL est intransigeant avec les objets qui n'existent pas, donc avec PostGIS < 2.5 ça finira toujours en erreur du genre ERREUR: la fonction st_astext(geometry, integer) n'existe pas. Ça ne marche pas comme en python où on peut protéger du code invalide par une condition, car les objets sont contrôlés avant le calcul des conditions.

Autrement dit, ceci n'est pas possible :

SELECT
    CASE WHEN (
        SELECT regexp_split_to_array(installed_version, '[.]')::int[] >= ARRAY[2, 5, 0]
            FROM pg_available_extensions WHERE name = 'postgis'
        )
        THEN ST_AsText(ST_Extent(geom), 8)
        ELSE ST_AsText(ST_Extent(geom))
        END
    FROM schema_name.table_name ;

La seule solution que je vois est de récupérer dans Plume la version de PostGIS (et plus seulement son existence) et la fournir en argument aux fonctions plume.pg.queries.query_get_geom_centroid et plume.pg.queries.query_get_geom_extent, afin que celles-ci sachent si elles peuvent ou non utiliser l'argument maxdecimaldigits dans les requêtes qu'elles construisent.

Cela supposera de disposer d'une fonction query_extension_version pour récupérer la version d'une extension disponible sur la base, ce qui aura certainement d'autres usages (par exemple dans le futur proche où on aura besoin de contrôler les versions de PlumePg pour savoir si certaines fonctionnalités peuvent être activées).

Est-ce que ça vous irait comme de cette façon ?

GilGuillouet commented 2 years ago

L'emprise (Bbox) récupérée sur les CSW de Géo-IDE était exprimée en coordonnées géographiques ce qui imposait de garder 8 décimales pour avoir l'ordre de grandeur du millimètre. Dans le cas d'une emprise exprimée en projection comme celles en Lambert 93 utilisée dans l'exemple, conserver 8 chiffes est totalement sans intérêt et même potentiellement générateur d'incompréhension pour un utilisateur qui pourrait s'imaginer une précision importante. Je doute que les contours de PPR par exemple aient été numérisés avec un tel précision. Si on veut parler de qualité de données, la précision en fait partie et devrait être maitrisée par le producteur. Par défaut il ne faudrait pas dépasser 3 chiffres après la virgule quand on exprime les coordonnées en mètres et certainement la plupart du temps se limiter au mètre. Dans le cadre de l'amélioration de la qualité ce point devra être discuté. Il faut être en accord avec ce qui est fourni dans les métadonnées. La COVADIS avait retenue l'échelle de saisie, très discutable mais qui reposait sur la fait qu'une saisie faite sur la carte à 1:25000 entrainait une précision planimétrique de l'ordre de 2.5m, à partir d’objets de la BDTOPO plutôt de l'ordre de 1m... On est loin la plupart du temps,sauf relevé terrain, de 2 ou 3 chiffres après la virgule...

alhyss commented 2 years ago

Absolument d'accord avec tout ce que tu écris, mais non ne maîtrisons ni le référentiel utilisé ni le contexte. Rien dans Plume n'interdit de tracer ou calculer des géométries en WSG 84, par exemple, et dans ce cas une précision de 3 décimales serait vraiment trop faible, même pour un périmètre de PPR. Plume utilise simplement le référentiel courant du canevas pour les tracés manuels, le référentiel déclaré pour la couche pour les calculs côté QGIS et le référentiel déclaré pour le champ de géométrie pour les calculs côté PostgreSQL, il peut s'agir de n'importe quoi.

L'avantage de fixer une valeur par défaut à 8 décimales, c'est qu'on limite déjà le problème sans prendre trop de risque. Ensuite, si l'ADL sait que les personnes susceptibles d'éditer ces métadonnées ne travaillent qu'en Lambert 93, il pourra modifier ce paramètres via les global settings de QGIS (certes, sous réserve qu'il ait mis ça en place pour son service). Il est aussi toujours possible de tronquer manuellement les valeurs en fonction de la précision effective des géométries de la couche considérée (les WKT sont éditables), ce qui est toujours plus facile à faire que de rajouter des chiffres...

Et puis la métadonnée sur la précision sert à ça, au fond : faute d'avoir des géométries dont la précision apparente est cohérente avec la précision de numérisation, savoir jusqu'à quelle point la précision apparente est significative.

Est-ce que tu vois une alternative ? Définir des précisions par défaut variables selon le référentiel me semblerait beaucoup trop coûteux pour des catégories de métadonnées qui ne sont au fond pas très utiles en local.

WREATCHED commented 2 years ago

https://user-images.githubusercontent.com/66324136/159496741-15c6af13-ea1f-49a5-802d-f9bf2f19ddb1.mp4

POUR GG, mais LL peut regarder bien sûr J'ai donc revu mes traitements pour générer le wkt, je repasse par la création d'une géométrie @LESLIE est-ce que qi je reprends ton wkt issue de postgis et que moi je le retransforme, ça devrait être OK , non ?

alhyss commented 2 years ago

Tu veux dire en faisant ce genre de manip ?

geom_wkt = QgsGeometry.fromWkt(postgis_wkt).asWkt(precision=wktMaxDecimalDigits)

Alors, oui, ça me semble acceptable, même s'il est un peu dommage de passer par ce genre de bricolage quand PostGIS est aussi capable de gérer la précision.

GilGuillouet commented 2 years ago

@alhyss Ok a priori il faut rester comme ça si on n'a pas d'autres solutions. Le champ précision est là pour donner l'information qu'il ne faut pas tenir compte des chiffres non significatifs!

WREATCHED commented 2 years ago

Implémenté dans la version 0.3 Bëta image

alhyss commented 2 years ago

Implémenté par @WREATCHED sur la v0.3 bêta.