• Willkommen im Geoclub - dem größten deutschsprachigen Geocaching-Forum. Registriere dich kostenlos, um alle Inhalte zu sehen und neue Beiträge zu erstellen.

GIS Problem - punkte im Umkreis von 5km (weltweit)

visionmaster

Geonewbie
Hallo zusammen,

ich bin noch neu im Thema GIS und befasse mich aktuell mit folgendem Problem:

Ich habe mir PostGIS auf einer PostgreSQL DB installiert und nun folgende Tabelle mit Punkten die weltweit verteilt sind.
Code:
id    name    type    geom
Die Spalte
Code:
geom
beinhaltet die Position der Punkte. Definiert mit der SRID 4326

Sagen wir mal das wären Schulen
Code:
type = 'schule'
und Krankenhäuser
Code:
type = 'krankenhaus'
Nun möchte ich eine Abfrage machen, die mir die Schulen und die Krankenhäuser im Umkreis von 5km zeigt.

Eine Abfrage in der Art:
Code:
SELECT p1.name as schule, p2.name as krankenhaus from
punkte p1, punkte p2
where ST_dwithin(p1, p2, 5000)
and p1.type = 'schule' and p2.type = 'krankenhaus'

funktioniert leider nicht, da st_dwithin immer in Winkelgraden rechnet. Die 50000 sind also Winkeleinheiten.
Code:
ST_dwithin(p1::geometry, p2::geometry, 5000)
macht es leider auch nicht besser.

Habe ich einen Fehler in der Speicherung meiner Daten? Welche SRID muss ich denn verwenden? Oder habe ich da etwas noch nicht richtig verstanden?

Gruß
Stefan
 

moenk

Administrator
Teammitglied
Wie schon im OSM-Forum beantwortet, diese Funktion hier sollte sein was Du suchst: http://www.postgis.org/docs/ST_Distance_Sphere.html
Dabei empfehle ich vorher die Menge "konservativ zu approximieren" (also durch ein Subselect einzuschränken).
 
OP
V

visionmaster

Geonewbie
also in etwa so?
Code:
SELECT p1.name as schule, p2.name as krankenhaus from
punkte p1, punkte p2
where 
ST_Distance_Sphere(p1, p2) < 5000
and p1.type = 'schule' and p2.type = 'krankenhaus'

aber wenn ich mir das hier anschaue
http://postgis.refractions.net/documentation/manual-2.0SVN/ST_DWithin.html
dort steht als Aufrufmethode:
Code:
boolean ST_DWithin(geography gg1, geography gg2, double precision distance_meters);
also müsste das doch eigentlich funktionieren, oder nicht?
Code:
where
ST_dwithin(p1::geography, p2::geography, 5000) = true
 
OP
V

visionmaster

Geonewbie
es funktioniert damit, allerdings wird der gist index nicht gezogen.
Habe es jetzt so gelöst:
Code:
from p1 inner join p2
on st_dwithin(p1.geom, p2.geom, 0.1) = true
where st_distance_sphere(p1.geom, p2.geom) < 5000
mit 0,1 Grad decke ich auf jeden Fall meine 5km ab und es wird der Gist indext gezogen und über die where Bedingung schränke ich dann genau auf die 5km Grenze ein.

Diese variante
Code:
from p1 inner join p2
on st_distance_sphere(p1.geom, p2.geom) < 5000
läuft bei ca 4000 verwendete Punkten 55 Sekunden, und meine obere Variante dauert ca 1. Sekunde
Fakter 55 schneller :shocked:
 

moenk

Administrator
Teammitglied
Das ist auch eine Form die konservative Approximation zu implementieren. Ob über ein join oder ein subselect hängt auch von der Menge der Daten ab die verbunden werden, aber auf jeden Fall müssen die teueren Vergleiche nicht mehr so oft durchgeführt werden.
 
Oben