Einführung in GeoTools

1. Übersicht

In diesem Artikel werden die Grundlagen der Open-Source-Java-Bibliothek von GeoTools erläutert - für die Arbeit mit Geodaten . Diese Bibliothek bietet kompatible Methoden zur Implementierung von Geografischen Informationssystemen (GIS) und implementiert und unterstützt viele Standards des Open Geospatial Consortium (OGC).

Während das OGC neue Standards entwickelt, werden diese von den GeoTools implementiert, was es für die Geodatenarbeit sehr praktisch macht.

2. Abhängigkeiten

Wir müssen die GeoTools-Abhängigkeiten zu unserer Datei pom.xml hinzufügen . Da diese Abhängigkeiten nicht in Maven Central gehostet werden, müssen wir auch ihre Repositorys deklarieren, damit Maven sie herunterladen kann:

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

Danach können wir unsere Abhängigkeiten hinzufügen:

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

3. GIS und Shapefiles

Um die GeoTools-Bibliothek praktisch nutzen zu können, müssen wir einige Dinge über geografische Informationssysteme und Shapefiles wissen .

3.1. GIS

Wenn wir mit geografischen Daten arbeiten möchten, benötigen wir ein geografisches Informationssystem (GIS). Mit diesem System können geografische Daten dargestellt, erfasst, gespeichert, bearbeitet, analysiert oder verwaltet werden .

Ein Teil der geografischen Daten ist räumlich - sie beziehen sich auf konkrete Orte auf der Erde. Die räumlichen Daten werden normalerweise von den Attributdaten begleitet. Attributdaten können zusätzliche Informationen zu jedem der räumlichen Merkmale sein.

Ein Beispiel für geografische Daten wären Städte. Der tatsächliche Standort der Städte sind die räumlichen Daten. Zusätzliche Daten wie der Name der Stadt und die Bevölkerung würden die Attributdaten bilden.

3.2. Shapefiles

Für die Arbeit mit Geodaten stehen verschiedene Formate zur Verfügung. Raster und Vektor sind die beiden primären Datentypen.

In diesem Artikel erfahren Sie, wie Sie mit dem Vektordatentyp e arbeiten . Dieser Datentyp kann als Punkte, Linien oder Polygone dargestellt werden.

Um Vektordaten in einer Datei zu speichern, verwenden wir ein Shapefile . Dieses Dateiformat wird verwendet, wenn mit dem Datentyp Geodatenvektor gearbeitet wird. Außerdem ist es mit einer Vielzahl von GIS-Software kompatibel.

Wir können GeoTools verwenden, um Shapefiles Funktionen wie Städte, Schulen und Sehenswürdigkeiten hinzuzufügen .

4. Features erstellen

In der GeoTools- Dokumentation wird angegeben, dass ein Feature alles ist, was auf einer Karte gezeichnet werden kann, z. B. eine Stadt oder ein Wahrzeichen. Und wie bereits erwähnt, können Features nach ihrer Erstellung in Dateien gespeichert werden, die als Shapefiles bezeichnet werden .

4.1. Geodaten aufbewahren

Bevor wir ein Feature erstellen, müssen wir seine Geodaten oder die Längen- und Breitengradkoordinaten seines Standorts auf der Erde kennen. Bei Attributdaten müssen wir den Namen des Features kennen, das wir erstellen möchten.

Diese Informationen finden Sie im Internet. Einige Websites wie simplemaps.com oder maxmind.com bieten kostenlose Datenbanken mit Geodaten an.

Wenn wir den Längen- und Breitengrad einer Stadt kennen, können wir sie leicht in einem Objekt speichern. Wir können ein Kartenobjekt verwenden , das den Städtenamen und eine Liste seiner Koordinaten enthält.

Erstellen wir eine Hilfsmethode, um das Speichern von Daten in unserem Map- Objekt zu vereinfachen :

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

Füllen wir nun unser Kartenobjekt aus :

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

Wenn wir eine CSV-Datenbank herunterladen, die diese Daten enthält, können wir einfach einen Reader erstellen, um die Daten abzurufen, anstatt sie in einem Objekt wie hier zu speichern.

4.2. Feature-Typen definieren

Jetzt haben wir also eine Karte der Städte. Um Features mit diesen Daten erstellen zu können, müssen Sie zuerst deren Typ definieren. GeoTools bietet zwei Möglichkeiten zum Definieren von Feature-Typen.

Eine Möglichkeit besteht darin, die createType- Methode der DataUtilites- Klasse zu verwenden:

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

Eine andere Möglichkeit ist die Verwendung eines SimpleFeatureTypeBuilder , der mehr Flexibilität bietet . Zum Beispiel können wir das Koordinatenreferenzsystem für den Typ festlegen und eine maximale Länge für das Namensfeld festlegen:

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

Beide Typen speichern die gleichen Informationen. Der Standort der Stadt wird als Punkt und der Name der Stadt als Zeichenfolge gespeichert .

Sie haben wahrscheinlich bemerkt, dass die Typvariablen TYPE und CITY mit allen Großbuchstaben wie Konstanten benannt sind. Typvariablen sollten als endgültige Variablen behandelt und nach ihrer Erstellung nicht geändert werden. Daher kann diese Art der Benennung verwendet werden, um genau dies anzuzeigen.

4.3. Feature-Erstellung und Feature-Sammlungen

Sobald wir den Feature-Typ definiert haben und über ein Objekt verfügen, das die zum Erstellen von Features erforderlichen Daten enthält, können wir sie mit ihrem Builder erstellen.

Lassen Sie uns einen SimpleFeatureBuilder instanziieren , der unseren Feature-Typ bereitstellt:

SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(CITY);

Wir benötigen außerdem eine Sammlung, um alle erstellten Feature-Objekte zu speichern:

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.

Wir sollten bedenken, dass GeoTools eine lebendige Bibliothek ist und dieser Artikel nur als grundlegende Einführung in die Bibliothek dient. Auch GeoTools ist nicht nur auf die Schaffung Vektordatentypen beschränkt - es kann auch zu schaffen oder zur Arbeit mit Rasterdatentypen verwendet werden.

Den vollständigen Beispielcode für diesen Artikel finden Sie in unserem GitHub-Projekt. Dies ist ein Maven-Projekt, daher sollten Sie es importieren und so ausführen können, wie es ist.