GeoJSON troppo ingombrante - cosa fare?


19

Sto usando leaflet.js per consentire agli utenti Web di selezionare una regione. Le regioni valide sono gli Stati Uniti, le provvigioni canadesi e i paesi del mondo (tranne Stati Uniti e Canada). Ho creato un file di forma usando Qgis e l'ho salvato come geojson. Ho semplificato il più possibile le geometrie.

Lo shapefile risultante è 400kb, ma il geojson è oltre un megabyte. Questo è più grande di quanto vorrei. Devo ridurre il sovraccarico della rete coinvolto nel trasferimento di queste informazioni.

Qual è il modo giusto per farlo? Le opzioni che posso immaginare sono:

  1. Servire il file geojson compresso con gzip, decomprimerlo sul client.
  2. Analizzare lo shapefile sul client su geojson
  3. Genera le mie tessere dal file di forma e servile

Se qualcuno potesse dirmi quale opzione è la migliore (o nessuna delle precedenti), la apprezzerei!


Noto che hai detto di aver provato a semplificare la geometria, ma hai provato a utilizzare un algoritmo di semplificazione GIS e a controllare i risultati? Potrebbe anche aiutare a vedere quale parte di JSON occupa più spazio.
BradHards,

1
Assicurati che GeoJSON non sia stampato in modo grazioso, eliminando tutto lo spazio bianco non necessario contribuirai a ridurre il file, non necessariamente di una quantità enorme, ma tutto aiuta!
CHenderson,

Risposte:


13

Prima di percorrere percorsi più laboriosi, l'opzione più semplice è quella di ridurre la geometria. Quali sono i tuoi set di dati di origine? Come li hai semplificati? Quanto ha ridotto le dimensioni del file geojson?

Se sei sicuro di aver fatto tutto il possibile su quanto sopra, allora il frutto più basso delle tue opzioni è

  1. Servire il file geojson compresso con gzip, decomprimerlo sul client.

Tutti i browser moderni eseguono automaticamente la decompressione dei dati compressi con gzip, quindi è solo un caso di configurare il server Web per comprimere i dati prima dell'invio. Questo è normalmente relativamente semplice, con molto materiale disponibile per Apache , IIS o Nginx

Il mio consiglio sarebbe quello di provare prima questo, test, quindi se la latenza / risposta / dimensione dei dati non è accettabile, quindi passare ad altre opzioni. Sarei anche cauto nel cercare di ottimizzare prematuramente, cercherò di capire perché è necessario ridurre la dimensione dei dati e, una volta che si hanno motivi difficili (e numeri) per farlo, quindi implementare iterativamente le modifiche e ripetere i test per vedere cosa guadagni che stai ottenendo.


13

Mapshaper.org è un pratico strumento online gratuito che ti consente di caricare un file geojson, visualizzarlo come una mappa, quindi scegliere uno dei tre alogritim di semplificazione di cui puoi regolare la forza con un cursore.

Aggiorna la mappa e evidenzia in rosso tutti i luoghi in cui si verifica una perdita di integrità come una sovrapposizione tra due regioni. C'è un pulsante 'fix' che di solito (ma non sempre) risolve tali problemi.

È possibile trovare un livello di semplificazione accettabile ed esportare il file geojson appena semplificato.

Ovviamente questo dipende dal livello di dettaglio di cui hai bisogno, ma i risultati possono essere impressionanti. Ad esempio, ecco la mappa della Scozia da un file geojson da 40 MB:

inserisci qui la descrizione dell'immagine

Un'applicazione del 99% lo riduce a un file di 441 kb senza sovrapposizioni e perdita di dettagli invisibili a questo livello di zoom:

inserisci qui la descrizione dell'immagine

Un'applicazione del 99,95% (fino a 29kb) mostra quale tipo di semplificazione del percorso viene applicata (e riesce comunque a evitare sovrapposizioni, ed è perfettamente adatta per usi come la cloropleth a livello nazionale):

inserisci qui la descrizione dell'immagine


Uso sempre questo strumento. È eccellente!
Mike Furlender,

1
Sei un vero toccasana !!
Khizar,

6

Mi chiedo se potresti sfruttare la compressione trovata in questa risposta che parla di comprimere il GeoJSON con topojson .

Non so se Leaflet sarà ancora in grado di leggere il GeoJSON - qualcosa da provare =)

Maggiori informazioni su topojson: https://github.com/mbostock/topojson/


Leaflet.GeoJSON non analizza i dati dell'arco, quindi questo approccio non funzionerà
smcphill

Il volantino non può nativamente ma puoi usare topojson sul lato client per farlo, esempio di topojson sul volantino , sebbene quell'esempio capiti di usare d3 per renderlo.
Calvin,

1
Ho avuto un file geoJson da 27 MB. Sono andato su mapshaper.org e dopo l'esportazione semplificata (1,0%) e topojson è diventato 122kb. Successivamente, ho aggiunto il codice topoJson Leaflet da github.com/shramov/leaflet-plugins/blob/master/layer/vector/… alla mia app e fatto quanto segue: nuovo L.TOPOJSON ("myExported.topojson"). ToGeoJson ().
StackUnder

3

Sono d'accordo con @Kelso sopra sulla semplificazione della geometria.

Se non hai accesso al tuo server per sgonfiare facilmente i dati con gzip, puoi dare un'occhiata alla libreria MessagePack per serializzare il tuo geoJSON in dati binari (credo che sia un'implementazione delle specifiche BSON che viene utilizzata da cose come MongoDB per memorizzare i dati, ma potrei sbagliarmi) . Ci sono librerie in Python e javascript (tra le altre) che puoi usare per serializzare / deserializzare i dati.


2
MessagePack non è legato alla BSON (in realtà è meglio in molti casi secondo stackoverflow.com/questions/6355497/... . Maggiori informazioni interessanti su MessagePack e specificamente GeoJSON può essere trovato alla nelsonslog.wordpress.com/2012/06/22/checking -out-msgpack .
Kelso

Grazie @Kelso - ha aggiornato la risposta. E anche un buon articolo!
om_henners,

1

Vorrei solo suggerire di creare il proprio array procedurale di oggetti Polygon Leaflet. Sono d'accordo con GeoJSON che è troppo grande. I nomi delle chiavi degli oggetti sono molto descrittivi ma forse anche inutilmente lunghi. Faccio questo tipo di cose:

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);

È semplice. È molto più leggero di GeoJSON in questo modo:

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

    //etc...

E ripeti per ogni singolo poligono ... ugh ... imo troppo gonfio. Aggiunge molti byte al tuo JS. Come ho detto, i nomi delle chiavi sono simpatici e descrittivi ... ma sono lunghi e aggiungono molti byte inutili al tuo JS.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.