GeoJSON demasiado voluminoso: ¿qué hacer?

19

Estoy usando leaflet.js para permitir a los usuarios web seleccionar una región. Las regiones válidas son estados de EE. UU., Providencias canadienses y países del mundo (excepto EE. UU. Y Canadá). Yo mismo construí un shapefile usando Qgis y lo guardé como geojson. Simplifiqué las geometrías tanto como pude.

El archivo de forma resultante es de 400 kb, pero el geojson tiene más de un megabyte. Esto es más grande de lo que me gustaría. Necesito reducir la sobrecarga de la red involucrada en la transferencia de esta información.

¿Cuál es la forma correcta de hacer esto? Las opciones que puedo imaginar son:

  1. Servir el archivo geojson comprimido, descomprimir en el cliente.
  2. Analiza el shapefile en el cliente para geojson
  3. Generar mis propios mosaicos desde el shapefile y servirlos

Si alguien pudiera decirme qué opción es la mejor (o ninguna de las anteriores), ¡lo agradecería!

Mike Furlender
fuente
Observé que dijiste que intentaste simplificar la geometría, pero ¿intentaste usar un algoritmo de simplificación SIG y comprobar los resultados? También podría ser útil observar qué parte del JSON ocupa más espacio.
BradHards
1
Asegúrese de que GeoJSON no esté bien impreso, eliminar todos los espacios en blanco innecesarios ayudará a hacer el archivo más pequeño, ¡no necesariamente en una gran cantidad, pero todo ayuda!
CHenderson

Respuestas:

13

Antes de seguir caminos más laboriosos, la opción más simple es reducir la geometría. ¿Cuáles son sus conjuntos de datos de origen? ¿Cómo los simplificaste? ¿Cuánto redujo esto el tamaño del archivo geojson?

Si está seguro de haber hecho todo lo posible en lo anterior, entonces el fruto más bajo de sus opciones es

  1. Servir el archivo geojson comprimido, descomprimir en el cliente.

Todos los navegadores modernos desempaquetan automáticamente los datos comprimidos, por lo que solo se trata de configurar su servidor web para que empaque los datos antes de enviarlos. Esto normalmente es relativamente sencillo, con mucho material disponible para Apache , IIS o Nginx

Mi consejo sería probar esto primero, probar, luego, si el tamaño de latencia / respuesta / datos no es aceptable, luego pasar a otras opciones. También sería cauteloso de tratar de optimizar prematuramente, buscaría determinar por qué necesita reducir el tamaño de los datos, y una vez que tenga razones (y números) para hacerlo, implemente de forma iterativa los cambios y vuelva a probar para ver qué ganancias que estás obteniendo.

Kelso
fuente
13

Mapshaper.org es una práctica herramienta gratuita en línea que le permite cargar un archivo geojson, mostrarlo como un mapa y luego elegir uno de los tres algoritmos de simplificación que puede ajustar con un control deslizante.

Actualiza el mapa y resalta en rojo cualquier lugar donde haya una pérdida de integridad como una superposición entre dos regiones. Hay un botón 'arreglar' que generalmente (pero no siempre) soluciona tales problemas.

Puede encontrar un nivel de simplificación que sea aceptable y exportar el archivo geojson recién simplificado.

Obviamente, esto depende del nivel de detalle que necesite, pero los resultados pueden ser impresionantes. Por ejemplo, aquí está el mapa de Escocia desde un archivo geojson de 40mb:

ingrese la descripción de la imagen aquí

Una aplicación del 99% lo reduce a un archivo de 441 kb sin superposiciones y pérdida de detalles que es invisible en este nivel de zoom:

ingrese la descripción de la imagen aquí

Una aplicación de 99.95% (hasta 29kb) muestra qué tipo de simplificación de ruta se está aplicando (y aún se las arregla para evitar solapamientos, y es perfectamente adecuada para usos como el cloroplasto a nivel nacional):

ingrese la descripción de la imagen aquí

user56reinstatemonica8
fuente
Yo uso esta herramienta todo el tiempo. ¡Es excelente!
Mike Furlender
1
¡¡Eres un salvavidas!!
Khizar
6

Me pregunto si podría hacer uso de la compresión que se encuentra en esta respuesta que habla sobre la compresión de GeoJSON con topojson .

No sé si Leaflet todavía podrá leer el GeoJSON, algo para probar =)

Más sobre topojson: https://github.com/mbostock/topojson/

SaultDon
fuente
Leaflet.GeoJSON no analiza datos de arco, por lo que este enfoque no funcionará
smcphill
El folleto no puede de forma nativa, pero puede usar topojson en el lado del cliente para hacerlo, ejemplo de topojson en el folleto , aunque ese ejemplo usa d3 para representarlo.
Calvin
1
Tenía un archivo geoJson de 27 MB. Fui a mapshaper.org y después de simplificar (1.0%) y exportar topojson se convirtió en 122kb. Después de eso agregué el código de folleto de topoJson de github.com/shramov/leaflet-plugins/blob/master/layer/vector/… a mi aplicación e hice lo siguiente: nuevo L.TOPOJSON ("myExported.topojson"). ToGeoJson ().
StackUnder
3

Estoy de acuerdo con @Kelso arriba en simplificar su geometría.

Si no tiene acceso a su servidor para desinflar los datos con gzip fácilmente, puede echar un vistazo a la biblioteca MessagePack para serializar su geoJSON en datos binarios (creo que es una implementación de la especificación BSON que utilizan MongoDB para almacenar datos, pero podría estar equivocado) . Hay bibliotecas en Python y javascript (entre otras) que puede usar para serializar / deserializar los datos.

om_henners
fuente
2
MessagePack no está relacionado con BSON (en realidad es mejor en muchos casos según stackoverflow.com/questions/6355497/… . Puede encontrar más información interesante sobre messagepack y específicamente geojson en nelsonslog.wordpress.com/2012/06/22/checking -out-msgpack .
Kelso
Gracias por eso @Kelso - actualicé la respuesta. ¡Y buen artículo también!
om_henners
1

Sugeriría simplemente crear su propia matriz de procedimientos de objetos Leaflet Polygon. Estoy de acuerdo con que GeoJSON sea demasiado grande. Los nombres de las claves de los objetos son muy descriptivos, pero también pueden ser innecesariamente largos. Hago este tipo de cosas:

objects = [];
objects.push( new L.polygon([[1,1],[1,2],[3,4]],options );
objects.push( new L.polygon([[4,7],[8,27],[35,66]],options );
objects.push( new L.polygon([[3,5],[56,24],[13,49]],options );
objects.push( new L.polygon([[13,7],[7,68],[23,9]],options );
layerGroup = L.layerGroup(objects).addTo(map);

Es sencillo. Es mucho más ligero que GeoJSON como este:

{ "type": "FeatureCollection",
  "features": [
    { "type": "Feature",
      "geometry": {"type": "Polygon",
      "coordinates": [1,1],[1,2],[3,4]},
      },

    //etc...

Y repita para cada polígono ... ugh ... imo demasiado hinchado. Agrega muchos bytes a su JS. Como dije, los nombres clave son agradables y descriptivos ... pero son largos y agregan muchos adiós innecesarios a su JS.

Jake Wilson
fuente