Introduzione a GeoTools

1. Panoramica

In questo articolo, esamineremo le basi della libreria Java open source GeoTools, per lavorare con i dati geospaziali . Questa libreria fornisce metodi conformi per l'implementazione di Geographic Information Systems (GIS) e implementa e supporta molti standard Open Geospatial Consortium (OGC).

Quando l'OGC sviluppa nuovi standard, vengono implementati da GeoTools, il che lo rende molto utile per il lavoro geospaziale.

2. Dipendenze

Dovremo aggiungere le dipendenze di GeoTools al nostro file pom.xml . Poiché queste dipendenze non sono ospitate su Maven Central, dobbiamo anche dichiarare i loro repository in modo che Maven possa scaricarle:

  osgeo Open Source Geospatial Foundation Repository //download.osgeo.org/webdav/geotools/   opengeo OpenGeo Maven Repository //repo.opengeo.org  

Successivamente, possiamo aggiungere le nostre dipendenze:

 org.geotools gt-shapefile 15.2   org.geotools gt-epsg-hsql 15.2 

3. GIS e shapefile

Per avere un uso pratico della libreria GeoTools, avremo bisogno di sapere alcune cose sui sistemi informativi geografici e sugli shapefile .

3.1. GIS

Se vogliamo lavorare con dati geografici, avremo bisogno di un sistema informativo geografico (GIS). Questo sistema può essere utilizzato per presentare, acquisire, archiviare, manipolare, analizzare o gestire dati geografici .

Una parte dei dati geografici è spaziale: fa riferimento a luoghi concreti sulla terra. I dati spaziali sono generalmente accompagnati dai dati degli attributi. I dati degli attributi possono essere qualsiasi informazione aggiuntiva su ciascuna delle caratteristiche spaziali.

Un esempio di dati geografici sarebbero le città. La posizione effettiva delle città sono i dati spaziali. Dati aggiuntivi come il nome della città e la popolazione costituirebbero i dati degli attributi.

3.2. Shapefile

Sono disponibili diversi formati per lavorare con i dati geospaziali. Raster e vettoriale sono i due tipi di dati primari.

In questo articolo, vedremo come lavorare con il tipo di dati vettoriali e . Questo tipo di dati può essere rappresentato come punti, linee o poligoni.

Per memorizzare i dati vettoriali in un file, useremo uno shapefile . Questo formato di file viene utilizzato quando si lavora con il tipo di dati vettore geospaziale. Inoltre, è compatibile con un'ampia gamma di software GIS.

Possiamo usare GeoTools per aggiungere funzionalità come città, scuole e punti di riferimento agli shapefile .

4. Creazione di caratteristiche

La documentazione di GeoTools specifica che un elemento è tutto ciò che può essere disegnato su una mappa, come una città o un punto di riferimento. E, come abbiamo detto, una volta create, le caratteristiche possono essere salvate in file chiamati shapefile .

4.1. Conservazione dei dati geospaziali

Prima di creare un elemento, dobbiamo conoscere i suoi dati geospaziali o le coordinate di longitudine e latitudine della sua posizione sulla terra. Per quanto riguarda i dati degli attributi, dobbiamo conoscere il nome dell'elemento che vogliamo creare.

Queste informazioni possono essere trovate sul web. Alcuni siti come simplemaps.com o maxmind.com offrono database gratuiti con dati geospaziali.

Quando conosciamo la longitudine e la latitudine di una città, possiamo facilmente memorizzarle in qualche oggetto. Possiamo usare un oggetto Map che conterrà il nome della città e un elenco delle sue coordinate.

Creiamo un metodo di supporto per facilitare la memorizzazione dei dati all'interno del nostro oggetto Map :

private static void addToLocationMap( String name, double lat, double lng, Map
    
      locations) { List coordinates = new ArrayList(); coordinates.add(lat); coordinates.add(lng); locations.put(name, coordinates); }
    

Ora compiliamo il nostro oggetto Mappa :

Map
    
      locations = new HashMap(); addToLocationMap("Bangkok", 13.752222, 100.493889, locations); addToLocationMap("New York", 53.083333, -0.15, locations); addToLocationMap("Cape Town", -33.925278, 18.423889, locations); addToLocationMap("Sydney", -33.859972, 151.211111, locations); addToLocationMap("Ottawa", 45.420833, -75.69, locations); addToLocationMap("Cairo", 30.07708, 31.285909, locations);
    

Se scarichiamo un database CSV che contiene questi dati, possiamo facilmente creare un lettore per recuperare i dati invece di conservarli in un oggetto come qui.

4.2. Definizione dei tipi di funzionalità

Quindi, ora abbiamo una mappa delle città. Per poter creare caratteristiche con questi dati, dobbiamo prima definire il loro tipo. GeoTools offre due modi per definire i tipi di feature.

Un modo è quello di utilizzare il createType metodo della DataUtilites classe:

SimpleFeatureType TYPE = DataUtilities.createType( "Location", "location:Point:srid=4326," + "name:String");

Un altro modo è utilizzare un SimpleFeatureTypeBuilder , che fornisce maggiore flessibilità . Ad esempio, possiamo impostare il sistema di riferimento delle coordinate per il tipo e possiamo impostare una lunghezza massima per il campo del nome:

SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setName("Location"); builder.setCRS(DefaultGeographicCRS.WGS84); builder .add("Location", Point.class); .length(15) .add("Name", String.class); SimpleFeatureType CITY = builder.buildFeatureType();

Entrambi i tipi memorizzano le stesse informazioni. La posizione della città viene memorizzata come punto e il nome della città viene memorizzato come stringa .

Probabilmente hai notato che le variabili di tipo TYPE e CITY sono denominate con tutte le lettere maiuscole, come le costanti. Le variabili di tipo dovrebbero essere trattate come variabili finali e non dovrebbero essere modificate dopo che sono state create , quindi questo modo di denominazione può essere utilizzato per indicare proprio questo.

4.3. Creazione di feature e raccolte di feature

Una volta che abbiamo definito il tipo di caratteristica e abbiamo un oggetto che ha i dati necessari per creare le caratteristiche, possiamo iniziare a crearle con il loro costruttore.

Istanziamo un SimpleFeatureBuilder che fornisce il nostro tipo di funzionalità:

SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(CITY);

Avremo anche bisogno di una raccolta per memorizzare tutti gli oggetti feature creati:

DefaultFeatureCollection collection = new DefaultFeatureCollection();

Since we declared in our feature type to hold a Point for the location, we'll need to create points for our cities based on their coordinates. We can do this with the GeoTools's JTSGeometryFactoryFinder:

GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);

Note that we can also use other Geometry classes like Line and Polygon.

We can create a function that will help us put features in the collection:

private static Function
    
     , SimpleFeature> toFeature(SimpleFeatureType CITY, GeometryFactory geometryFactory) { return location -> { Point point = geometryFactory.createPoint( new Coordinate(location.getValue() .get(0), location.getValue().get(1))); SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(CITY); featureBuilder.add(point); featureBuilder.add(location.getKey()); return featureBuilder.buildFeature(null); }; }
    

Once we have the builder and the collection, by using the previously created function, we can create features and store them in our collection:

locations.entrySet().stream() .map(toFeature(CITY, geometryFactory)) .forEach(collection::add);

The collection now contains all the features created based on our Map object that held the geospatial data.

5. Creating a DataStore

GeoTools contains a DataStore API that is used to represent a source of geospatial data. This source can be a file, a database, or some service that returns data. We can use a DataStoreFactory to create our DataStore, which will contain our features.

Let's set the file that will contain the features:

File shapeFile = new File( new File(".").getAbsolutePath() + "shapefile.shp");

Now, let's set the parameters that we are going to use to tell the DataStoreFactory which file to use and indicate that we need to store a spatial index when we create our DataStore:

Map params = new HashMap(); params.put("url", shapeFile.toURI().toURL()); params.put("create spatial index", Boolean.TRUE);

Let's create the DataStoreFactory using the parameters we just created, and use that factory to create the DataStore:

ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory(); ShapefileDataStore dataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params); dataStore.createSchema(CITY);

6. Writing to a Shapefile

The last step that we need to do is to write our data to a shapefile. To do this safely, we are going to use the Transaction interface that is a part of the GeoTools API.

This interface gives us the possibility to easily commit our the changes to the file. It also provides a way to perform a rollback of the unsuccessful changes if some problem occurs while writing to the file:

Transaction transaction = new DefaultTransaction("create"); String typeName = dataStore.getTypeNames()[0]; SimpleFeatureSource featureSource = dataStore.getFeatureSource(typeName); if (featureSource instanceof SimpleFeatureStore) { SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource; featureStore.setTransaction(transaction); try { featureStore.addFeatures(collection); transaction.commit(); } catch (Exception problem) { transaction.rollback(); } finally { transaction.close(); } }

The SimpleFeatureSource is used to read features, and the SimpleFeatureStore is used for read/write access. It is specified in the GeoTools documentation that using the instanceof method for checking if we can write to the file is the right way to do so.

This shapefile can later be opened with any GIS viewer that has shapefile support.

7. Conclusion

In this article, we saw how we can make use of the GeoTools library to do some very interesting geo-spatial work.

Although the example was simple, it can be extended and used for creating rich shapefiles for various purposes.

Dovremmo tenere a mente che GeoTools è una libreria vivace e questo articolo serve solo come introduzione di base alla libreria. Inoltre, GeoTools non si limita alla creazione di soli tipi di dati vettoriali, ma può anche essere utilizzato per creare o lavorare con tipi di dati raster.

Puoi trovare il codice di esempio completo utilizzato in questo articolo nel nostro progetto GitHub. Questo è un progetto Maven, quindi dovresti essere in grado di importarlo ed eseguirlo così com'è.