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 != %s
ORDER BY (
CASE WHEN a.item_type='POINT' THEN ST_Distance(
(SELECT CASE b.item_type WHEN 'POINT' THEN b.point  ELSE b.geometry END
FROM 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 END
FROM 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 END
FROM 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)

Tags: , , , ,

Leave a Reply