Ähm, 9.1 hat KNNGIST, KNN Gist for PostGIS in Place - Postgres OnLine Journal , solltest Du im Auge behalten ...
Ansonsten: warte auf den Gisman ;-)
Andreas
Hallo zusammen,
ich hänge nun schon seit ein paar Stunden an einem Problem.
Ich möchte zu einem Punkt den nächsten Nachbarn suchen (PostGIS), um das ganze performanter zu machen benutze ich ich eine BOX3D um meinen Bereich in dem der nächste Nachbar gesucht werden soll.
Ich bekomme allerdings ständig 0 Zeilen zurückgeliefert. Mein Punkt (Parameter) ist ok, die Box die erstellt wird stimmt und wenn ich die Query so, also ohne PGSQL-Funktion ausführe funktioniert es.Code:CREATE OR REPLACE FUNCTION my_nearest_srtm_neighbor(p_in geometry) RETURNS TABLE(id integer, height integer, point geometry, distance double precision) AS $$ DECLARE x double precision := ST_X(p_in); y double precision := ST_Y(p_in); mybox box3d := ('BOX3D(' || (x-0.005) || ' ' || (y-0.005) || ', ' || (x+0.005) || ' ' || (y+0.005) || ')')::box3d; BEGIN RAISE NOTICE 'Point is: %', ST_AsText(p_in); RAISE NOTICE 'Box is: %', ST_AsText(mybox); RETURN QUERY SELECT id, height, point, ST_Distance(point, p_in) FROM srtm WHERE point && mybox AND ST_Distance(point, p_in) = ( SELECT MIN(ST_Distance(point, p_in)) FROM srtm WHERE point && mybox ); END; $$ LANGUAGE plpgsql;
Was lustigerweise auch funktioniert ist folgendes:
Ich lasse mir also nicht die ganze Zeile ausgeben sondern lediglich die ID des Punktes. Das funktioniert wunderbar. Warum funktioniert mein erster Ansatz nicht?Code:DROP FUNCTION my_nearest_srtm_neighbor(geometry); /*TABLE(id integer, height integer, point geometry, distance double precision)*/ CREATE OR REPLACE FUNCTION my_nearest_srtm_neighbor(p_in geometry) RETURNS integer AS $$ DECLARE x double precision := ST_X(p_in); y double precision := ST_Y(p_in); mybox box3d := ('BOX3D(' || (x-0.005) || ' ' || (y-0.005) || ', ' || (x+0.005) || ' ' || (y+0.005) || ')')::box3d; t_row RECORD; BEGIN RAISE NOTICE 'Point is: %', ST_AsText(p_in); RAISE NOTICE 'Box is: %', ST_AsText(mybox); SELECT id, height, point, ST_Distance(point, p_in) INTO t_row FROM srtm WHERE point && mybox AND ST_Distance(point, p_in) = ( SELECT MIN(ST_Distance(point, p_in)) FROM srtm WHERE point && mybox ); RETURN t_row.id; END; $$ LANGUAGE plpgsql;
Vielen Dank für eure Hilfe!
Viele Grüße
PS: Ich hoffe ich habe die Board-Konventionen mit CodeTags etc. eingehalten![]()
Ähm, 9.1 hat KNNGIST, KNN Gist for PostGIS in Place - Postgres OnLine Journal , solltest Du im Auge behalten ...
Ansonsten: warte auf den Gisman ;-)
Andreas
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Hmm, ich hab leider nur Postgres 8.4 zur Verfügung. Aber ich glaube das Problem liegt nicht an PostGIS sondern in PL/PGSQL (?).
Die Abfrage so funktioniert ja wie gesagt und auch recht performant (~40ms) bei 10 Mio Einträgen.
Danke trotzdem für den Hinweis![]()
Bzzzzt...schon da
Ich bin noch nicht ganz fertig mit dem Lesen, aber erstmal folgende Fragen:
1. Warum benutzt du eine 3DBox? Du benutzt keine 3D-Daten.
2. Warum eine Boundingbox und kein Buffer? Wäre IMHO logischer, weil du dann wirklich nur die Punkte abfragst, die innerhalb einer definierten Distance liegen. Bei der Box fragst du Punkte auch ab die bis sqrt(2) deiner eigentlichen Distance entfernt sind. Und du sparst dir das erzeugen der Box.
3. Ich würde die Distance der der Box/des Buffers als Parameter der Funktion übergeben und nicht fest einbauen.
Ansonsten kann ich in der Abfrage selbst im Moment keinen Fehler entdecken, wie du sagst, funktioniert ja die Abfrage, nur die Rückgabe nicht so wie du willst. Ich werd morgen mal eine klene Testanwendung damit bauen, denke ich.
Noch als Anmerkung: PostGIS2.0 kann direkt auf die SRTM-Raster zugreifen (Ich versuche im Moment genau das zum Laufen zu kriegen) und dort z.B. an einem Punkt Höhenwerte oder andere Sachen der jeweiligen Rasterzelle abfragen.
Grüssle Uwe
Have a lot of fun!
Hi,
also mal der Reihe nach
1.
Ich hab mich hierbei an die PostGIS-Dokumentation gehalten: Chapter*4.*Using PostGIS: Data Management and Queries
Ich habs gerade auch mit der 2D-Box versucht, die Abfrage dauert im Schnitt doppelt so lange (~110ms). Frag mich nicht warum!
2.
Aus gleichem Grund wie bei 1.
Mir ist kein anderes Verfahren bekannt, wie funktioniert das mit dem Buffer?
3.
Ja, kann man natürlich machen^^ Brauch ich aber im Moment nicht, kann man ja dann noch schnell ändern.
Anmerkung:
Ja toll, so langsam glaub ich echt ich muss upgraden... Es war allerdings schon ein Kampf mein Debian zu überzeugen 8.4 anstatt 8.3 zu verwenden. Ist leider squeeze. Danach hatte ich noch schöne Stunden mit der PG-Config weil die nicht korrekt gemerged hatte... Eigentlich wollte ich mir sowas nochmal ersparen... :/
Danke schonmal für deine Hilfe!
Was ich auch gerade versucht habe war: Mehrere OUT-Parameter bestimmen und diese als SET zurückzugeben. Dann sind auch alle leer. Sehr komisch das ganze
Viele Grüße,
Wolfgang
Guten Morgen!
Zum Buffer:
Du würdest deine Räumliche Bedingung etwa so formulieren:
Allerdings musst du die Distance auch hier entsprechend des räumlichen Bezugs abgeben, also bei srid=4326 in Dezimalgrad. Aber das ist bei der Box-Methode letzlich genauso. Könnte mir auch vorstellen, das das im Falle von Punkten etwas schneller ist. Die genaue Syntax musst du noch in der Doku nach lesen, die find ich hier grad nicht.Code:... where point && st_buffer(point, distance) ...
Gruß Uwe
EDIT: Muß kurz zurückrudern mit ST_Buffer: ST_DWithin ist die bessere und schnellere Funktion: http://postgis.refractions.net/docs/ST_DWithin.html
Geändert von Gisman (22.01.2012 um 11:08 Uhr)
Have a lot of fun!
Hab mal was zusammengebastelt, was gerade bei mir funktioniert hat.
Prinzipieller Unterschied ist, das ich erst mit dem With-statement erst eine Untermenge der Punkte bilde, auf der dann die eigentliche Distance-Abfrage stattfindet. Die Begrenzung findet jetzt mit ST_DWITHIN statt, was die Box erspart. Ich spiel halt gern rumCode:CREATE OR REPLACE FUNCTION my_nearest_srtm_neighbor(p_in geometry) RETURNS TABLE(id integer, height numeric, point geometry, distance double precision) AS $$ DECLARE BEGIN RAISE NOTICE 'Point is: %', ST_AsText(p_in); RETURN QUERY with t1 as (select a.id, a.x, a.y, a.height, a.geom, st_distance(p_in, a.geom) as dist from test_daten a where st_dwithin(p_in, a.geom, 2)) select t1.id as id, t1.height as height, t1.geom as point, t1.dist as distance from t1 where t1.dist = (select min(dist) from t1); END; $$ LANGUAGE plpgsql;
Bei mir hat das aber erst funktioniert, als ich die Ausgabespalten so benannt habe wir sie in der Ausgabe-Tabelle heißen sollen, d.h. es könnte bei dir zu Problemen geführt haben, das die ST_Distance Anweisung einen falschen Namen für die Ausgabe generiert.
Viele Grüße und schön Sonntag noch
Uwe
PS: Die Testdaten hatte ich so generiert:
Code:create table test_daten ( id integer primary key, x integer, y integer, height numeric); select addgeometrycolumn('public', 'test_daten', 'geom', -1, 'POINT', 2); insert into test_daten (id, x, y, height, geom) select x.x*1000+y.y as id, x.x, y.y, random()*100 as height, st_geometryfromtext('POINT('||x.x||' '||y.y||')', -1) as geom from generate_series(0,100) as x(x), generate_series(0,100) as y(y)
Have a lot of fun!
Hi,
leider funktioniert deine Funktion bei mir nicht. Ich erhalte folgenden Fehler:
Das gleiche erhalte ich auch wenn ich bei meiner Funktion ST_Distance(..) AS distance machen will.Code:ERROR: syntax error at or near "$2" LINE 1: ...ere st_dwithin( $1 , a.geom, 2)) select t1.id as $2 , t1.he... ^ QUERY: with t1 as (select a.id, a.x, a.y, a.height, a.geom, st_distance( $1 , a.geom) as dist from test_daten a where st_dwithin( $1 , a.geom, 2)) select t1.id as $2 , t1.height as $3 , t1.geom as $4 , t1.dist as $5 from t1 where t1.dist = (select min(dist) from t1) CONTEXT: SQL statement in PL/PgSQL function "my_nearest_srtm_neighbor" near line 13 ********** Fehler ********** ERROR: syntax error at or near "$2" SQL Status:42601 Kontext:SQL statement in PL/PgSQL function "my_nearest_srtm_neighbor" near line 13
Woran kann denn das schon wieder liegen?
Viele Grüße,
Wolfgang
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Hi,
das mache ich doch garnicht oder?
Ich übergebe eig. nur einen Punkt.
Viele Grüße,
Wolfgang
Links: Tobias Bauer - IT- und Funkdienstleistungen - Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen - Funkforum
Lesezeichen