Multipolygon bzw. Multilinestring in Point-Geometrie auflösen

Guten Morgen,

Ich habe in versch. PG-Tabellen Daten in Form vom Geometrietyp Multipolygon bzw. Multilinestring abgelegt. Ich möchte jetzt auf PG-Basis die einzelnen Punkte der Geometrie entnehmen, und in einer neuen Tabelle mit Point-Geomtrie speichern.
Für den ersten Punkt gibt es ja folgende Lösung, ich möchte das halt für alle Punkte, und duplikate sind mir egal.
SELECT asewkt(the_geom), ST_AsText(ST_StartPoint(the_geom::geometry)) FROM tabelle;

Danke für eure Hilfe
Alexander

Dafür gibt es in PostGIS die Möglichkeit, die Polygone in Linien aufzulösen, die man dann in ihre Punkte zerlegen kann. AFAIR gibt es in PostGIS 1.5 dafür eine Funktion, andernfalls kann man sich das auch selber schreiben. Einfach mal ein bisschen im PostGIS -Handbuch schmökern, da findet sich dann schon was. Wenn ich nachher Zeit hab, such ich mal genauer und poste es hier. Ich hab das schon mal gemacht.

Gruß Uwe

EDIT: Ok, ich finds grad nicht. Prinzipiell lief das so, das man in einer Funktion ein Polygon zu Linien gemacht hat (z.B. als Ring o.ä), dann durch die einzelnen Linien gellop ist und jeweils die Anuzahl der Punkte bestimmt hat. In einem weiteren Loop hat man dann die einzelnen Punkte (mit PointN) in die ergebnisenge geschrieben. Als Ergebnis kann ein Rowset der Punkte incl. einer ID raus, das man per insert in eine eigene Tabelle schreiben konnte.

Ich hoff das hat etwas geholfen…

CU

Edit2: TADA!

CREATE OR REPLACE FUNCTION getborderpoints(IN geom geometry, OUT idx integer, OUT xcoord numeric, OUT ycoord numeric)
  RETURNS SETOF record AS
$BODY$
--DECLARE

--  xcoord numeric;
--  ycoord numeric;
  
BEGIN
  for i in 1 .. (select st_numpoints($1)) loop
    idx := i;
    xcoord := st_x(st_pointn($1,i));
    ycoord := st_y(st_pointn($1,i));
    raise notice '%, %, %', i, xcoord, ycoord;
    return next;
  end loop;
  return;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE

Du musst noch die Geometrie als Ausgabeparameter definieren.

CU

Hallo Uwe,
ich bin ja noch neu hier, und weiss nicht ob ich das richtig mache.
Ich habe die Funktion mit PGAdmin eingetragen.
Dann habe ich mit “select getborderpoints(the_geom) from geom_lin;” folgendes Ergebniss.
Was meinst du mit “noch die Geometrie als Ausgabeparameter definieren”.
Danke
Alexander

####################################
NOTICE: 1, 3464820.996, 5775033.223
ERROR: set-valued function called in context that cannot accept a set
CONTEXT: PL/pgSQL function “getborderpoints” line 12 at return next

********** Fehler **********

ERROR: set-valued function called in context that cannot accept a set
SQL Status:0A000
Kontext:PL/pgSQL function “getborderpoints” line 12 at return next
##################################

Hm, ich hab den Kontext nicht mehr ganz vor Augen in dem ioch das geschrieben hab. AFAIR kann man ihm Linien und Polygone übergeben (verm. keine Multi-Geometrien!). So wie es ist leider es dir eine Liste mit x und y-Koordinaten und eine ID wie in der ersten Zeile der Ausgabe. Damit du den Punkt als Geometrie bekommst mußt du noch in der ersten Zeile die eine Geometrie als Ausgabe-Parameter definieren und natürlich ausgeben. Also etwa so:

CREATE OR REPLACE FUNCTION getborderpoints(IN geom geometry, OUT idx integer, OUT xcoord numeric, OUT ycoord numeric, OUT geom geometry)
  RETURNS SETOF record AS
$BODY$
--DECLARE

--  xcoord numeric;
--  ycoord numeric;

  
BEGIN
  for i in 1 .. (select st_numpoints($1)) loop
    idx := i;
    xcoord := st_x(st_pointn($1,i));
    ycoord := st_y(st_pointn($1,i));
    geom := st_pointn($1,i);
    raise notice '%, %, %', i, xcoord, ycoord;
    return next;
  end loop;
  return;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE

Die Fehlermeldung selbst besagt, das du das Ergebnis irgendwohin schreiben willst, wo es nicht geht.

Gruß Uwe

Hallo Uwe,
da du ja erwähnt hast, das Postgis 1.5 eine Funktion dafür hat, habe ich kurzerhand 1.5 installiert.
Hier die Lösung (auch für Multilinestrings sowie Multipolygone):
SELECT ST_X(geom), ST_Y(geom) from (SELECT (ST_DumpPoints(the_geom)).* FROM the_geom) as foo;

Da PG 1.5 auf einer anderen Maschine als meine Daten läuft hier noch die Lösung mit dblink:

dblink_connection zur entfernten Maschine:
SELECT dblink_connect(‘myconn’, ‘hostaddr=ip port=5432 dbname=data user=xxx password=yyy’);

hier der SQL mit dblink und auch noch einer Where-Bedingung auf eine Spalte:
SELECT ST_X(geom), ST_Y(geom) from (SELECT (ST_DumpPoints(the_geom)).*
FROM dblink(‘myconn’, ‘SELECT spalte, the_geom FROM public.tabelle’)
AS t1(spalte character varying(3), the_geom geometry) WHERE spalte=‘123’) as foo;

dblink_connection zur entfernten Maschine nachher wieder trennen:
SELECT dblink_disconnect(‘myconn’);

Hierbei werden Duplikate ausgegeben.

Gruß
Alexander

So geht das auch in PostGIS <1.5. Bei mir war eine Anforderung, die Punkte der Reihe nach mit ID als csv zu liefern. Wie dem auch sei, ich kann mich daran erinnern, das ich beim Schmökern in der Doku von 1.5 sowas ähnliches gefunden hatte.
Wird Zeit sich mal wieder mit einer vernünftigen DB zu beschäftigen. Ich werd so langsam ganz orakelig… :wink:

CU UWe