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?

Robert Špendl
la source
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)"
dbaston
la source
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;
thoomasbro
la source