Tagzania – Postgis – GeoDjango – Nearest Neighbours Distance (II)
FASE 1: Problema & Solución
En los comienzos se realizaban consultas SQL sobre diferentes geometrías. Algo así:
SELECT a.* FROM items AS a WHERE a.id != %sORDER BY (CASE WHEN a.item_type='POINT' THEN ST_Distance(
(SELECT CASE b.item_type WHEN 'POINT' THEN b.point ELSE b.geometry ENDFROM items AS b WHERE b.id= %s), a.point)
WHEN a.item_type='POLYLINE' THEN ST_Distance(
(SELECT CASE c.item_type WHEN 'POINT' THEN c.point ELSE b.geometry ENDFROM items AS c WHERE c.id= %s), ST_StartPoint(a.geometry)
WHEN a.item_type='POLYGON' THEN ST_Distance((SELECT CASE c.item_type WHEN 'POINT' THEN c.point ELSE b.geometry ENDFROM items AS c WHERE c.id= %s), ST_Centroid(a.geometry)) END) LIMIT %s;
Nos dimos cuenta que teniamos lineas de mas de 5000 intersecciones/puntos, por lo que realizar el cálculo de distancia sobre cada intersección/punto de esa linea, era demasiado costoso para el servidor. Y a la hora de visualizarlo en el mapa, tardaba demasiado en dibujarlo.
Solución: Decidimos guardar la versión simplificada ( geodjango – simplify() ) de cada geometría. Crear un elemento neutro, en caso de lineas y poligonos, de modo simplificado. Utilizando diferentes criterios de tolerancia, a cuanto más puntos más tolerancia, menos intersecciones/puntos.
simple_line = models.LineStringField(blank=True, null=True)
simple_polyline = models.PolygonField(blank=True, null=True)
…
if len(self.line.array) > 1000:
self.simple_line = self.line.simplify(tolerance = 0.0013)
else:
if len(self.line.array) > 400:
tzp.simple_line = self.line.simplify(tolerance = 0.0011)
else:
self.simple_line = self.line.simplify(tolerance = 0.0002)
Pero esto tampoco terminaba de ir del todo bien …
Segiamos mejorando ….
Próximamente la parte (III)