Bienvenue sur PostGIS.fr

Bienvenue sur PostGIS.fr , le site de la communauté des utilisateurs francophones de PostGIS.

PostGIS ajoute le support d'objets géographique à la base de données PostgreSQL. En effet, PostGIS "spatialise" le serverur PostgreSQL, ce qui permet de l'utiliser comme une base de données SIG.

Maintenu à jour, en fonction de nos disponibilités et des diverses sorties des outils que nous testons, nous vous proposons l'ensemble de nos travaux publiés en langue française.

source: trunk/workshop-foss4g/validity.rst @ 81

Revision 62, 7.5 KB checked in by thomasg, 12 years ago (diff)

Fin correction typo et orthographe V2 du document

RevLine 
[1]1.. _validity:
2
[50]3Partie 20 : Validité
[1]4====================
5
[62]6Dans 90% des cas la réponse à la question "pourquoi mes requêtes me renvoient un message d'erreur du type 'TopologyException' error"" est : "un ou plusieurs des arguments passés sont invalides". Ce qui nous conduit à nous demander : que signifie invalide et pourquoi est-ce important ?
[1]7
[50]8Qu'est-ce que la validité ?
9---------------------------
[1]10
[29]11La validité est surtout importante pour les polygones, qui définissent des aires et requiÚrent une bonne structuration. Les lignes sont vraiment simples et ne peuvent pas être invalides ainsi que les points.
[1]12
[29]13Certaines des rÚgles de validation des polygones semble évidentes, et d'autre semblent arbitraires (et le sont vraiment).
[1]14
[62]15 * Les contours des polygones doivent être fermés.
16 * Les contours qui définissent des trous doivent être inclus dans la zone définie par le contour extérieur.
[29]17 * Les contours ne doivent pas s'intersecter (ils ne doivent ni se croiser ni se toucher).
18 * Les contours ne doivent pas toucher les autres contours, sauf en un point unique.
[1]19
[62]20Les deux derniÚres rÚgles font partie de la catégorie arbitraire. Il y a d'autres moyens de définir des polygones qui sont consistants mais les rÚgles ci-dessus sont celles utilisées dans le standard :term:`OGC` :term:`SFSQL` que respecte PostGIS.
[1]21
[62]22La raison pour laquelle ces rÚgles sont importantes est que les algorithmes de calcul dépendent de cette structuration consistante des arguments. Il est possible de construire des algorithmes qui n'utilisent pas cette structuration, mais ces fonctions tendent à être trÚs lentes, étant donné que la premiÚre étape consiste à "analyser et construire  des structures à l'intérieur des données".
[1]23
[50]24Voici un exemple de pourquoi cette structuration est importante. Ce polygone n'est pas valide :
[1]25
26::
27
28  POLYGON((0 0, 0 1, 2 1, 2 2, 1 2, 1 0, 0 0));
[62]29
[29]30Vous pouvez comprendre ce qui n'est pas valide en regardant cette figure :
[1]31
32.. image:: ./validity/figure_eight.png
33
[62]34Le contour externe est exactement en forme en 8 avec une intersection au milieu. Notez que la fonction de rendu graphique est tout de même capable d'en afficher l'intérieur, donc visuellement cela ressemble bien à une "aire" : deux unités carré, donc une aire couplant ces deux unités.
[1]35
[29]36Essayons maintenant de voir ce que pense la base de données de notre polygone :
[1]37
38.. code-block:: sql
39
40  SELECT ST_Area(ST_GeometryFromText('POLYGON((0 0, 0 1, 1 1, 2 1, 2 2, 1 2, 1 1, 1 0, 0 0))'));
[62]41
[1]42::
43
[62]44    st_area
[1]45   ---------
46          0
47
[62]48Que ce passe-t-il ici ? L'algorithme qui calcule l'aire suppose que les contours ne s'intersectent pas. Un contour normal devra toujours avoir une aire qui est bornée (l'intérieur) dans un sens de la ligne du contour (peu importe quelle sens, juste *un* sens). Néanmoins, dans notre figure en 8, le contour externe est à droite de la ligne pour un lobe et à gauche pour l'autre. Cela entraine que les aires qui sont calculées pour chaque lobe annulent la précédente (l'une vaut 1 et l'autre -1) donc le résultat est une "aire de zéro".
[1]49
50
[50]51Détecter la validité
52--------------------
[1]53
[62]54Dans l'exemple précédent nous avions un polygone que nous **savions** non-valide. Comment déterminer les géométries non valides dans une tables d'un million d'enregistrements ? Avec la fonction :command:`ST_IsValid(geometry)` utilisée avec notre polygone précédent, nous obtenons rapidement la réponse :
[1]55
56.. code-block:: sql
57
58  SELECT ST_IsValid(ST_GeometryFromText('POLYGON((0 0, 0 1, 1 1, 2 1, 2 2, 1 2, 1 1, 1 0, 0 0))'));
59
[62]60::
[1]61
62  f
63
[62]64Maintenant nous savons que l'entité est non-valide mais nous ne savons pas pourquoi. Nous pouvons utiliser la fonction :command:`ST_IsValidReason(geometry)` pour trouver la cause de non validité :
[1]65
66.. code-block:: sql
67
68  SELECT ST_IsValidReason(ST_GeometryFromText('POLYGON((0 0, 0 1, 1 1, 2 1, 2 2, 1 2, 1 1, 1 0, 0 0))'));
69
70::
71
72  Self-intersection[1 1]
73
[29]74Vous remarquerez qu'en plus de la raison (intersection) la localisation de la non validité (coordonnée (1 1)) est aussi renvoyée.
[1]75
[62]76Nous pouvons aussi utiiliser la fonction :command:`ST_IsValid(geometry)` pour tester nos tables :
[1]77
78.. code-block:: sql
79
[62]80  -- Trouver tous les polygones non valides et leur problÚme
[1]81  SELECT name, boroname, ST_IsValidReason(the_geom)
82  FROM nyc_neighborhoods
83  WHERE NOT ST_IsValid(the_geom);
84
85::
86
[62]87           name           |   boroname    |                     st_isvalidreason
[1]88 -------------------------+---------------+-----------------------------------------------------------
89  Howard Beach            | Queens        | Self-intersection[597264.083368305 4499924.54228856]
90  Corona                  | Queens        | Self-intersection[595483.058764138 4513817.95350787]
91  Steinway                | Queens        | Self-intersection[593545.572199759 4514735.20870587]
92  Red Hook                | Brooklyn      | Self-intersection[584306.820375986 4502360.51774956]
93
94
95
[29]96Réparer les invalides
97---------------------
[1]98
[62]99Commençons par la mauvaise nouvelle : il n'y a aucune garantie de pouvoir corriger une géométrie non valide. Dans le pire des scénarios, vous pouvez utiliser la fonction  :command:`ST_IsValid(geometry)` pour identifier les entités non valides, les déplacer dans une autre table, exporter cette table et les réparer à l'aide d'un outil extérieur.
[1]100
[62]101Voici un exemple de requête SQL qui déplace les géométries non valides hors de la table principale dans une table à part pour les exporter vers un programme de réparation.
[1]102
103.. code-block:: sql
104
[62]105  -- Table à part des géométries non-valides
[1]106  CREATE TABLE nyc_neighborhoods_invalid AS
107  SELECT * FROM nyc_neighborhoods
108  WHERE NOT ST_IsValid(the_geom);
[62]109
[29]110  -- Suppression de la table principale
[1]111  DELETE FROM nyc_neighborhoods
112  WHERE NOT ST_IsValid(the_geom);
113
[62]114Un bon outil pour réparer visuellement des géométries non valide est OpenJump (http://openjump.org) qui contient un outils de validation depuis le menu **Tools->QA->Validate Selected Layers**.
[1]115
[62]116Maintenant, la bonne nouvelle : un grand nombre de non-validités **peut être résolu dans la base de données** en utilisant la fonction : :command:`ST_Buffer`.
[1]117
[62]118Le coup du Buffer tire avantage de la maniÚre dont les buffers sont construits : une géométrie bufferisée est une nouvelle géométrie, construite en déplaçant les lignes de la géométrie d'origine. Si vous déplacez les lignes originales par *rien* (zero) alors la nouvelle géométrie aura une structure identique à l'originale, mais puisqu'elle utilise les rÚgles topologiques de l':term:`OGC`, elle sera valide.
119
[29]120Par exemple, voici un cas classique de non-validité - le "polygone de la banane" - un seul contour que crée une zone mais se touche, laissant un "trou" qui n'en est pas un.
[1]121
[62]122::
[1]123
124  POLYGON((0 0, 2 0, 1 1, 2 2, 3 1, 2 0, 4 0, 4 4, 0 4, 0 0))
[62]125
[1]126.. image:: ./validity/banana.png
127
[29]128En créant un buffer de zero sur le polygone retourne un polygone :term:`OGC` valide, le contour externe et un contour interne qui touche l'autre en un seul point.
[1]129
130.. code-block:: sql
131
132  SELECT ST_AsText(
133           ST_Buffer(
134             ST_GeometryFromText('POLYGON((0 0, 2 0, 1 1, 2 2, 3 1, 2 0, 4 0, 4 4, 0 4, 0 0))'),
135             0.0
136           )
137         );
138
139::
140
141  POLYGON((0 0,0 4,4 4,4 0,2 0,0 0),(2 0,3 1,2 2,1 1,2 0))
142
143.. note::
144
[62]145  Le "polygone banane" (ou "coquillage inversé") est un cas où le modÚle topologique de l':term:`OGC` et de ESRI diffÚrent. Le modÚle ESRI considÚre que les contours qui se touchent sont non valides et préfÚre la forme de banane pour ce cas de figure. Le modÚle de l'OGC est l'inverse.
146
Note: See TracBrowser for help on using the repository browser.