2016-06-16 16 views
0

Für meine Anwendung muss ich einen Punkt in meiner Datenbank finden, der dem vom Benutzer angegebenen Punkt am nächsten ist. Das ist mein Modell:Den nächstgelegenen Punkt zu einem benutzerdefinierten Ort finden

class WaysVerticesPgr(models.Model): 
    id = models.BigIntegerField(primary_key=True) 
    osm_id = models.BigIntegerField(unique=True, blank=True, null=True) 
    cnt = models.IntegerField(blank=True, null=True) 
    chk = models.IntegerField(blank=True, null=True) 
    ein = models.IntegerField(blank=True, null=True) 
    eout = models.IntegerField(blank=True, null=True) 
    lon = models.DecimalField(max_digits=11, decimal_places=8, blank=True, null=True) 
    lat = models.DecimalField(max_digits=11, decimal_places=8, blank=True, null=True) 
    the_geom = models.PointField(blank=True, null=True) 

Und ich diesen Code versuchen alle Punkte innerhalb eines kleinen Radius zu finden (in diesem Fall o.oo5 Grad), mit Anmerkungen versehen, den Abstand zwischen jedem von ihnen und einem Eingangspunkt, sie sortieren nach Entfernung und gibt die erste in der Reihe:

from django.contrib.gis.db.models.functions import * 
from .models import * 
from django.contrib.gis.geos import * 
from django.contrib.gis.measure import * 

def get_closest_point(input): 
    input_point_geometry=GEOSGeometry('POINT('+input+')') 
    closest = WaysVerticesPgr.objects.filter(the_geom__dwithin=(input_point_geometry,0.005)).annotate(distance_between=input_point_geometry.distance('the_geom')).order_by(distance_between)[:1] 
    return closest 

Aber ich erhalte eine Fehlermeldung ‚distance() funktioniert nur auf anderen GEOS Geometries‘. Wenn ich versuche, die Umwandlung the_geom zu GEOSGeometry Format:

closest = WaysVerticesPgr.objects.filter(the_geom__dwithin=(input_point_geometry,0.005)).annotate(distance_between=input_point_geometry.distance(GEOSGeometry('the_geom'))).order_by(distance_between)[:1] 

bekomme ich einen Fehler:

'String or unicode input unrecognized as WKT EWKT, and HEXEWKB'. Which is kind of strange because the_geom field has the format 0101000020E6100000E7525C55F65DA1BF8FF5793139C34940 that seems to be HEX.

Ich schaffte es in einem langen Weg zu tun, mit einer Schleife, aber das ist nicht schön aussieht und die Leistung ist nicht gut. Interessanterweise Umstellung auf GEOSGeometry arbeitet in diesem Fall:

def get_closest_point(input): 
    input_point_geometry=GEOSGeometry('POINT('+input+')') 
    closest = WaysVerticesPgr.objects.filter(the_geom__dwithin=(input_point_geometry,0.005)) 

    dict_closest = {} 
    list_closest = [] 
    for i in closest: 
     i = GEOSGeometry(i.the_geom) 
     distance_between=input_point_geometry.distance(i) 
     i = str(i.wkt) 
     dict_closest = {'Point':i,'Distance':distance_between} 
     list_closest.append(dict_closest) 
     sortlist=sorted(list_closest, key=itemgetter('Distance'), reverse=False) 
    return sortlist[0] 

Hat jemand eine Idee, wie man es in einem kurzen Weg funktioniert? Ich arbeite mit Django 1.9, Python 3.5 und Postgres 9.5 mit . Ich habe Leute in anderen Threads vorgeschlagen, die eine andere Abstandsfunktion verwenden, die wie distance = Distance (point1, point2) aussieht, aber es gibt mir den Fehler, dass 3 Argumente gegeben sind, während nur 1 oder 2 akzeptiert werden (eine Eingabe war zwei Punkte des GEOSGeometry-Formats)).

Ihre Hilfe wird sehr geschätzt!

Antwort

1

@ e4c5 Ja, ich habe es überprüft. Stellt fest, dass GeoQuerySet.distance Funktion seit Django 1.9 veraltet ist. Stattdessen dies für mich gearbeitet:

def get_closest_point(input): 
    input_point=GEOSGeometry('POINT('+input+')') 
    closest = WaysVerticesPgr.objects.filter(the_geom__dwithin=(input_point_geometry,0.005)).annotate(distance=Distance('the_geom', input_point)).order_by('distance').values('lon','lat')[0] 

Sie trotzdem danken (für deine Antwort gestimmt aber nicht wegen meines niedrigen Ruf anzuzeigen).

Verwandte Themen