Kreiskoordinaten manipulieren

Hallo Wissende,
ich habe in einer “Fremdanwendung” eine Kreisgeometrie mit 5 Punkten:
P1,P2,P3,PM,P4 (PM… Kreismittelpunkt)
Diese entspricht allerdings nicht der PostGIS-Definition. Ich müsste jetzt eigentlich nur PM entfernen und P1 anhängen.
Die sollte prinzipiell über die Manipulation von WKT kein Problem sein. Allerdings möchte ich vermeiden eine dafür eine eigene Funktion in der Fremddatenbank zu definieren.

Seht ihr eine Chance mit eingebauten PostGIS-Funktionen und SQL die entsprechende Manipulation vorzunehmen.

Gruß Steffen

zeig doch mal bitte die Tabellendefinition, paar Demodaten dazu, und was rauskommen soll.

Ja, allerdings wäre eine genauere Beschreibung dessen, was du vorliegen hast und was du tun willst hilfreich.

Gruß Uwe

Hallo,
danke für die Antworten.
Man kann ja bekanntermaßen einen Kreis aus 3 Punkten generieren (warum PostGIS 4 Punkte braucht erschließt sich mir allerdings nicht).
Der (vollständige) Kreis ist in PostGIS korrekt so definiert

CIRCULARSTRING Z( P1   , P2   , P3   , P4   , P1   )
CIRCULARSTRING Z(0 -1 0,-1 0 0, 0 1 0, 1 0 0,0 -1 0)

In der Fremddatenbank sieht das Ganze aber wie oben schon beschrieben aus:

CIRCULARSTRING Z( P1   , P2   , P3   , PM   , P4   )
CIRCULARSTRING Z(0 -1 0,-1 0 0, 0 1 0, 0 0 0, 1 0 0)

Daraus wird dann z.B. in QGIS natürlich kein “richtiger” Kreis.

Ich muss also aus dem Punktarray den 4. Punkt löschen und den ersten anfügen. Für so eine Aktion habe ich keine entsprechende PostGIS Funktion gefunden.
Es gibt eigentlich (fast) gar keine Kreismanipulationsfunktionen. Es würde mich aber nicht stören, wenn der Kreis nach der Manipulation als “LINESTRING” dargestellt wird.

… und wie gesagt, ich will die Orginaldaten nicht umschreiben, sondern per (Live) SQL-Abfrage in QGIS einbinden

Gruß Steffen

was sicher gehen sollte ist, wenn Du via st_astext(() und st_geomfromtext() und dazwischen mit Stringfunktionen hantierst.

gis=*# select st_geomfromtext('srid=0;circularstring(0 2, 2 0, 0 -2,-2 -2,0 2)');
                                                                                  st_geomfromtext                                                                                   
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 0108000000050000000000000000000000000000000000004000000000000000400000000000000000000000000000000000000000000000C000000000000000C000000000000000C000000000000000000000000000000040
(1 Zeile)

gis=*# select st_astext(st_geomfromtext('srid=0;circularstring(0 2, 2 0, 0 -2,-2 -2,0 2)'));
               st_astext                
----------------------------------------
 CIRCULARSTRING(0 2,2 0,0 -2,-2 -2,0 2)
(1 Zeile)

Notfalls dazu eine kleine Funktion schreiben und dann vielleicht einen (materialized) View bauen. Mal so als Idee.

Hallo,

ja über WKT und String wäre meine letzte Möglichkeit (habe schon damit gegonnen).
Wird aber ziemlich komplex, da ich die Originaldatenbank nicht manipulieren möchte, dh. weder eine Funktion noch eine View speichern will.

Gruß Steffen

Du solltest per st_dumppoints die einzelnen Punkte der Geometrie als Array bekommen und kannst dann darauf eine Umsortierung machen. Ich hab allerdings mit Circularstrings und so noch nicht wirklich viel gemacht, kann also nicht sagen was dabei rauskomt. Das Handbuch bietet aber einige Beispiele zu der Funktion. Wie das in QGIS funktioniert kann ich dir im Moment noch nicht sagen.

Gruß Uwe

Du kannst das SQL im DB-Manager von QGIS ausführen und das Ergebnis als Layer darstellen. Damit solltest du auf Änderungen an der Datenbank verzicheten können. Du findest ihn im Menü unter Datenbank/DB-Verwaltung. Je nach Alter der QGIS-Version mußt du ihn als PlugIn nachinstallieren. Es gibt wohl auch noch andere PlugIns die das machen können.

Gruß Uwe

Hallo Uwe,
danke für die Antworten. QGIS ist mir alles klar :-). Muss halt nur ein SQL “basteln”.
Ich mach es jetzt erst mal über WKT und schau mir danach mal st_dumppoints an.

Gruß Steffen

Hallo nochmal:

Nur so als kurzes Beispiel. Es entsorgt den 4. Punkt des Linestrings und fügt den Anfangspunkt ans Ende an.

select st_addpoint(st_removepoint(t1.geom, 3), st_startpoint(t1.geom)) 
  from (select st_geomfromtext('linestring(0 0, 4 0, 4 4, 0 4, 0 0)') as geom) t1

Die Überführung des Circularstrings in einen Linstring und zurück überlasse ich den geneigten Leser zur Übung :wink:

Viele Grüße Uwe

Hallo,
so hier erst mal die WKT-Lösung ohne Unterabfrage:

select *,
  st_setsrid(
    st_geomfromtext
    (
      array_to_string( 
          array_append( 
              array_append(
                   (string_to_array(ST_AsText(shape),','))[1:3],
                      substring((string_to_array(ST_AsText(shape),','))[5],
                                 1,length((string_to_array(ST_AsText(shape),','))[5])-1))
                        ,(string_to_array( substring(ST_AsText(shape),19),','))[1])
                    ,',') 
                       || ')')
   ,25833) as sid_shape from fremdtabelle

Schön bzw. übersichtlich sieht anders aus :rolleyes: . Einer Unterabfrage würde das Ganze vereinfachen - ich habe es aber im Moment noch nicht so richtig mit Unterabfragen, da diese in MSAccess recht wenig performant waren.

@Uwe:

Die Überführung des Circularstrings in einen Linstring und zurück überlasse ich den geneigten Leser zur Übung > :wink:

Das würde bei mir dann so aussehen:

select *,
  st_setsrid(st_geomfromtext('CIRCULARSTRING Z' || 
    substr(ST_AsText(st_addpoint(st_removepoint(t1.geom, 3), st_startpoint(t1.geom))),14)) ,25833) as sid_shape
		from (select *, st_geomfromtext( 
			'linestring Z' || substr(ST_AsText(shape),17)
			) as geom from fremdtabelle) t1

Muss jetzt mal schauen, wie die Geschwindigkeiten der beiden Varianten sind.

[EDIT]Variante 1 ist doch um ca. 30% schneller. Da werde ich wohl doch auf die unübersichtliche Variante setzen.[/EDIT]

**[EDIT2]**Diese Variante ist dann doch die Schnellste:

select *,
       st_setsrid( st_geomfromtext('CIRCULARSTRING Z' || 
           substr(ST_AsText(st_addpoint(st_removepoint(
                               st_geomfromtext('linestring Z' || substr(ST_AsText(shape),17) ), 3), 
                            st_startpoint(st_geomfromtext('linestring Z' || substr(ST_AsText(shape),17) )
                                         ))),14)
                 ),25833) as sid_shape
from fremdtabelle

[/EDIT2]
Vielen Dank für eure Hilfen!!

Gruß Steffen