datosgobar / georef-ar-api

API del Servicio de Normalización de Datos Geográficos de Argentina.
https://apis.datos.gob.ar/georef
MIT License
150 stars 31 forks source link

Normalización y georreferenciación de direcciones #192

Open federicotdn opened 5 years ago

federicotdn commented 5 years ago

La normalización y la georreferenciación de direcciones son dos componentes prioritarios de la API. La idea de este issue es resumir en qué estado se encuentra la API actualmente en relación a estos dos mecanismos, y qué aspectos faltan mejorar o corregir.

En principio, el ETL descarga la base de cuadras (secciones de calles) del portal de geoservicios de INDEC. Cada cuadra contiene los siguientes datos (entre otros):

Solo se incluyen las cuadras correspondientes a localidades censales con más de 10000 habitantes. Muchas de las cuadras tienen datos incompletos: las alturas iniciales y finales son 0.

Actualmente (31/05/2019), los datos de cuadras de las siguientes localidades censales son inválidos:

Por esta razón, el ETL también descarga datos de calles INDEC (no cuadras) para estas localidades censales. Los datos de calles son extremadamente similares a los de cuadras, por lo que se pueden reinterpretar las calles como cuadras tan largas como calles. Algunas de estas "cuadras" tienen más de una sección y no son siempre conexas, a diferencia de una cuadra normal que siempre es una recta simple.

A partir de los datos de cuadras extraídos (incluyendo la correción mencionada), se generan las calles (dentro del ETL). Para lograr esto, se combinan todas las cuadras con un mismo ID de calle, para generar la calle final. Como muchas cuadras tienen altura final e inicial igual a 0, los datos de calles también terminan estando incompletos (no hay datos de alturas). Todas las calles están disponibles en el recurso /calles.

A partir de los datos de calles (generados dentro del ETL), se generan los datos de intersecciones. Se calculan todas las intersecciones posibles de calles con otras calles. Algunos pares de calles comparten más de una intersección. Cada intersección tiene un ID de tres partes: el ID de la primera calle, el de la segunda, y el número de intersección entre las dos calles (desde 01 hasta 99).

Los tres conjuntos de datos (calles, cuadras e intersecciones) se almacenan dentro de archivos NDJSON (como las demás entidades geográficas) y se indexan del lado de la API.

En la API, cuando se consulta el recurso /direcciones, se realizan distintas búsquedas dependiendo de el tipo de dirección. Recordar que la API maneja tres tipos de direcciones:

Para los tres tipos de direcciones, se realiza en primer lugar una búsqueda de cuadras de la primera calle. Si hay altura, se limitan los resultados a cuadras que contengan la altura especificada. Acá es donde aparece el primer problema.

Muchas cuadras están indexadas, pero no cuentan con alturas. Por lo tanto, al momento de especificar una altura en la búsqueda, la cuadra no será encontrada. Por ejemplo, si se buscan cuadras con nombre "Santa Fe" y altura 1000, pero todas las cuadras de Santa Fe tienen alturas de 0 a 0, todas serán excluidas de los resultados. La única forma de solucionar esto es que los datos de origen sean más completos.

Si la cuadra se encuentra, y sus alturas iniciales y finales contienen la altura de la búsqueda, se puede proceder a calcular la posición geográfica de la altura. La cuenta consiste en realizar una interpolación desde el comienzo de la cuadra hasta el final, utilizando la altura como parámetro. Por ejemplo, si la cuadra va del 2000 al 3000, y la altura es 2500, la posición de la altura debe estar exactamente en la mitad de la cuadra. Para las "cuadras" generadas a partir de calles completas (para las localidades censales con cuadras inválidas) esta operación no siempre es posible, porque las "cuadras" no siempre tienen un tramo exacto.

Para los tipos de dirección intersección y entre calles, se ejecutan una o dos búsquedas más, para encontrar el resto de las calles. Si se especificó una altura, y si se pudo georreferenciarla sobre la calle, se intenta comprobar que efectivamente que el o los cruces de las dos o tres calles están efectivamente cerca de la altura especificada. Por ejemplo, si se busca "Santa Fe 2500 y Belgrano", y se logra encontrar la posición de "Santa Fe 2500", se puede comprobar entonces que el cruce entre Santa Fe y Belgrano está cerca de esa posición. La misma lógica aplica a direcciones entre calles. Es importante notar que si no se pudo calcular la posición de la altura sobre la primera calle, ninguna de estas operaciones son posibles, y la API directamente no devuelve resultados. Este problema también se resuelve teniendo datos de entrada más completos.

Otro problema que aparece a la hora de buscar direcciones de tipo intersección y entre calles es el cálculo de total e inicio. Para comprobar la existencia de direcciones de estos tipos, se requiere más de una búsqueda a Elasticsearch. Se debe, entonces, encontrar alguna forma de calcular el total de resultados posibles y el offset de la búsqueda afuera de Elasticsearch. El valor total representa el total de resultados que existen pero no necesariamente fueron devueltos. Calcular este valor con precisión requeriría buscar todas las direcciones posibles, aunque el usuario no las haya pedido, lo cual sería inconveniente. Idealmente, los valores total e inicio deberían tomar otro significado (o no ser utilizados) durante búsquedas de direcciones de más de una calle.

Los problemas a resolver, entonces, son:

federicotdn commented 5 years ago

Reemplaza https://github.com/datosgobar/georef-ar-api/issues/170 y https://github.com/datosgobar/georef-ar-api/issues/172.

federicotdn commented 5 years ago

Relacionado a https://github.com/datosgobar/georef-ar-api/issues/154.