PostGIS ST_Intersection von Polygonen kann Zeilen zurückgeben

9

Wenn Sie die Polygone einer Tabelle mit Polygonen in einer anderen beschneiden, kann ST_Intersection eine Reihe von Ergebnissen zurückgeben, die mit ST_Dump verarbeitet werden können. Die zurückgegebenen Mehrfachgeometrien sind nicht unbedingt ST_Polygon, sondern auch ST_LineString (wahrscheinlich auch ein Punkt). Also beim Ausführen einer Abfrage

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));

Beim Versuch, die Tabelle "c" mit abgeschnittenen Polygonen zu füllen, schlägt dies mit ERROR fehl: Der Geometrietyp (LineString) stimmt nicht mit dem Spaltentyp (Polygon) überein.

Ich habe eine weitere verschachtelte SELECT-Anweisung ausgeführt, sodass nur die Polygongeometrien durchgekommen sind, z.

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');

Da dies etwas umständlich ist, frage ich mich, ob es eine elegantere Lösung gibt, um ungültige Geometrien zu löschen.

Robert Špendl
quelle
Übrigens habe ich <! - language: lang-sql -> vor die Codeblöcke gesetzt, aber es gibt immer noch keine Hervorhebung. Irgendwelche Hinweise für einen Noob?
Robert Špendl
Um Code zu formatieren, fügen Sie ihn einfach ein, wählen Sie ihn aus und verwenden Sie die Schaltfläche Codebeispiel {}über dem Fenster zum Bearbeiten von Fragen.
PolyGeo
Hm, ich habe das gemacht, der Code ist als "Code" markiert, aber die Schlüsselwörter sind immer noch nicht farbig.
Robert Špendl
Normalerweise versuche ich hier nicht, SQL-Code zu verschönern, aber ich habe gerade einen Meta-Beitrag gefunden, der unter meta.stackexchange.com/questions/90521/… nützlich aussieht. Haben Sie eine "leere Zeile zwischen dem Kommentar und dem Code" hinterlassen?
PolyGeo
Ein Schnittpunkt zweier Geometrien kann jede Art von Geometrie ergeben. Ich denke, Ihre aktuelle Lösung ist die direkteste.
Mike T

Antworten:

9

Dies ist möglicherweise ein guter Ort, um eine SQL-Sprachfunktion zu verwenden. Hier ist eine kurze, die für diese Situation funktionieren sollte:

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;

Dadurch bleiben die polygonalen Komponenten einer Kreuzung erhalten, aber alles andere wird weggeworfen. Es wird immer ein MultiPolygon zurückgegeben, auch wenn Sie eine oder keine Komponenten haben.

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
quelle
3

Sehr gute Antwort von @dbaston. Die Rückgabe einer leeren Geometrie anstelle von null kann jedoch zu Problemen führen, da die zurückgegebene leere Geometrie kein srid enthält. St_Intersection gibt möglicherweise auch MultiPolygon zurück. Diese aktualisierte Funktion war wirklich nützlich für mich:

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
quelle