PostGIS ST_Intersection of polygones can return lines


9

Lors de la découpe des polygones d'une table avec des polygones dans une autre, ST_Intersection peut renvoyer un ensemble de résultats qui peuvent être gérés avec ST_Dump. Les multiples géométries renvoyées ne sont pas nécessairement ST_Polygon mais également ST_LineString (probablement aussi un point). Ainsi, lors de l'exécution d'une requête

INSERT INTO c (geom)
  (SELECT (ST_Dump(ST_Intersection(a.geom,b.geom))).geom
  FROM a INNER JOIN b ON ST_Intersects(a.geom, b.geom));

lorsque vous essayez de remplir le tableau "c" avec des polygones écrêtés, il échoue avec ERREUR: le type de géométrie (LineString) ne correspond pas au type de colonne (Polygon)

J'ai fait une autre instruction SELECT imbriquée, de sorte que seules les géométries de polygone ont traversé, comme:

INSERT INTO c (geom)
  (SELECT geom FROM
    (SELECT (ST_Dump(ST_Intersection(a.geom,b.geom))).geom
    FROM a INNER JOIN b ON ST_Intersects(a.geom, b.geom))) AS cl
    WHERE ST_GeometryType(cl.geom)='ST_Polygon');

Comme c'est un peu lourd, je me demande s'il existe une solution plus élégante pour supprimer des géométries invalides?


BTW, j'ai mis <! - language: lang-sql -> avant les blocs de code mais il n'y a toujours pas de highligting. Des conseils pour un noob?
— Robert Špendl

Pour formater le code, collez-le simplement, sélectionnez-le et utilisez le bouton Exemple de code {}au-dessus de la fenêtre d'édition de la question.
— PolyGeo

Hm, je l'ai fait, le code est marqué comme "code", mais les mots clés ne sont toujours pas colorés.
— Robert Špendl

Je n'essaye pas normalement de raffiner le code SQL ici, mais je viens de trouver une publication Meta qui semble utile sur meta.stackexchange.com/questions/90521/… - avez-vous laissé une "ligne vide entre le commentaire et le code"?
— PolyGeo

Une intersection de deux géométries peut donner n'importe quel type de géométrie, donc je pense que votre solution actuelle est la plus directe.
— Mike T

Réponses:


9

Cela pourrait être un bon endroit pour utiliser une fonction en langage SQL. Voici un rapide qui devrait fonctionner pour cette situation:

CREATE OR REPLACE FUNCTION PolygonalIntersection(a geometry, b geometry)
RETURNS geometry AS $$
SELECT ST_Collect(geom)
FROM 
(SELECT (ST_Dump(ST_Intersection(a, b))).geom 
UNION ALL
-- union in an empty polygon so we get an 
-- empty geometry instead of NULL if there
-- is are no polygons in the intersection
SELECT ST_GeomFromText('POLYGON EMPTY')) SQ
WHERE ST_GeometryType(geom) = 'ST_Polygon';
$$ LANGUAGE SQL;

Cela conservera les composants polygonaux d'une intersection, mais jetera tout le reste. Il renvoie toujours un MultiPolygon, même si vous avez un ou aucun composant.

WITH 
      square   as (SELECT ST_GeomFromText('POLYGON ((0 0, 0  1,  1  1,  1  0, 0 0))') AS geom),
biggersquare   as (SELECT ST_GeomFromText('POLYGON ((0 0, 0 10, 10 10, 10  0, 0 0))') AS geom),
adjacentsquare as (SELECT ST_GeomFromText('POLYGON ((0 0, 1  0,  1 -1, -1 -1, 0 0))') AS geom)   

SELECT ST_AsText(PolygonalIntersection(square.geom, biggersquare.geom))
  FROM square, biggersquare;
--"MULTIPOLYGON(((0 0,0 1,1 1,1 0,0 0)))"

SELECT ST_AsText(PolygonalIntersection(square.geom, adjacentsquare.geom))
  FROM square, adjacentsquare;
--"MULTIPOLYGON(EMPTY)"

3

Très bonne réponse de @dbaston. Cependant, le retour d'une géométrie vide au lieu de null peut entraîner des problèmes car la géométrie vide renvoyée n'a pas de srid. St_Intersection peut également renvoyer MultiPolygon. Cette fonction mise à jour m'a été vraiment utile:

CREATE OR REPLACE FUNCTION PolygonalIntersection(a geometry, b geometry)
RETURNS geometry AS $$
SELECT ST_Collect(geom)
FROM 
(SELECT (ST_Dump(ST_Intersection(a, b))).geom 
) SQ
WHERE ST_GeometryType(geom) = 'ST_Polygon' OR ST_GeometryType(geom) = 'ST_MultiPolygon';
$$ LANGUAGE SQL;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.