Рубрики
Без рубрики

Введение в геотуры

Краткое и практическое руководство по работе с геопространственными данными на Java с использованием библиотеки GeoTools с открытым исходным кодом.

Автор оригинала: baeldung.

1. Обзор

В этой статье мы рассмотрим основы библиотеки Java с открытым исходным кодом GeoTools для работы с геопространственными данными . Эта библиотека предоставляет совместимые методы реализации Географических информационных систем (ГИС), а также реализует и поддерживает многие стандарты Открытого геопространственного консорциума (OGC).

По мере того, как OGC разрабатывает новые стандарты, они внедряются GeoTools, что делает его довольно удобным для геопространственной работы.

2. Зависимости

Нам нужно будет добавить зависимости GeoTools в ваш pom.xml файл. Поскольку эти зависимости не размещены в Maven Central, нам также необходимо объявить их репозитории, чтобы Maven мог их загрузить:


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

После этого мы можем добавить наши зависимости:


    org.geotools
    gt-shapefile
    15.2


    org.geotools
    gt-epsg-hsql
    15.2

3. ГИС и шейп-файлы

Чтобы иметь какое-либо практическое использование библиотеки GeoTools, нам нужно знать несколько вещей о географических информационных системах и шейп-файлах .

3.1. ГИС

Если мы хотим работать с географическими данными, нам понадобится географическая информационная система (ГИС). Эта система может использоваться для представления, сбора, хранения, обработки, анализа или управления географическими данными .

Некоторая часть географических данных является пространственной – она ссылается на конкретные места на земле. Пространственные данные обычно сопровождаются атрибутивными данными. Атрибутивными данными могут быть любые дополнительные сведения о каждом из пространственных объектов.

Примером географических данных могут служить города. Фактическое местоположение городов – это пространственные данные. Дополнительные данные, такие как название города и население, будут составлять атрибутивные данные.

3.2. Шейп-файлы

Для работы с геопространственными данными доступны различные форматы. Растр и вектор-это два основных типа данных.

В этой статье мы рассмотрим, как работать с векторным типом данных e . Этот тип данных может быть представлен в виде точек, линий или полигонов.

Для хранения векторных данных в файле мы будем использовать шейп-файл . Этот формат файла используется при работе с типом геопространственных векторных данных. Кроме того, он совместим с широким спектром программного обеспечения для ГИС.

Мы можем использовать GeoTools для добавления таких функций, как города, школы и достопримечательности в шейп-файлы .

4. Создание функций

В документации GeoTools указывается, что объект-это все, что может быть нарисовано на карте, например город или какая-либо достопримечательность. И, как мы уже упоминали, после создания функции могут быть сохранены в файлы, называемые шейп-файлами .

4.1. Хранение Геопространственных Данных

Прежде чем создавать объект, мы должны знать его геопространственные данные или координаты долготы и широты его местоположения на земле. Что касается данных атрибутов, нам нужно знать имя объекта, который мы хотим создать.

Эту информацию можно найти в Интернете. Некоторые сайты, такие как simplemaps.com или maxmind.com предлагаем бесплатные базы данных с геопространственными данными.

Когда мы знаем долготу и широту города, мы можем легко хранить их в каком-либо объекте. Мы можем использовать объект Map , который будет содержать название города и список его координат.

Давайте создадим вспомогательный метод, чтобы облегчить хранение данных внутри нашего объекта 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);
}

Теперь давайте заполним наш Map объект:

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

Если мы загрузим некоторую базу данных CSV, содержащую эти данные, мы можем легко создать считыватель для извлечения данных, а не хранить их в объекте, как здесь.

4.2. Определение Типов объектов

Итак, теперь у нас есть карта городов. Чтобы иметь возможность создавать объекты с этими данными, нам сначала нужно определить их тип. GeoTools предлагает два способа определения типов объектов.

Один из способов-использовать метод CreateType класса Data Utilities :

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

Другой способ – использовать SimpleFeatureTypeBuilder , который обеспечивает большую гибкость . Например, мы можем установить систему координат для типа, и мы можем установить максимальную длину для поля имени:

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

Оба типа хранят одну и ту же информацию. Местоположение города хранится в виде Точки , а название города хранится в виде Строки .

Вы, вероятно, заметили, что переменные типа TYPE и CITY называются со всеми заглавными буквами, как константы. Переменные типа должны рассматриваться как окончательные переменные и не должны изменяться после их создания , поэтому этот способ именования может использоваться только для обозначения этого.

4.3. Создание функций и коллекций функций

Как только мы определили тип объекта и у нас есть объект, содержащий данные, необходимые для создания объектов, мы можем начать создавать их с помощью их конструктора.

Давайте создадим экземпляр SimpleFeatureBuilder , предоставляющий наш тип функций:

SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(CITY);

Нам также понадобится коллекция для хранения всех созданных объектов объектов:

DefaultFeatureCollection collection = new DefaultFeatureCollection();

Поскольку мы объявили в нашем типе объектов, что для местоположения требуется Точка , нам нужно создать точки для наших городов на основе их координат . Мы можем сделать это с помощью Geotools JTS Geometry FactoryFinder :

GeometryFactory geometryFactory
  = JTSFactoryFinder.getGeometryFactory(null);

Обратите внимание, что мы также можем использовать другие Геометрические классы, такие как Линия и Полигон .

Мы можем создать функцию , которая поможет нам поместить функции в коллекцию:

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

После того, как у нас есть конструктор и коллекция , используя ранее созданную функцию |, мы можем создавать функции и хранить их в нашей коллекции :

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

Теперь коллекция содержит все объекты, созданные на основе нашего объекта Map , который содержал геопространственные данные.

5. Создание хранилища данных

GeoTools содержит API хранилища данных , который используется для представления источника геопространственных данных. Этим источником может быть файл, база данных или какая-либо служба, возвращающая данные. Мы можем использовать DataStoreFactory для создания нашего хранилища данных , которое будет содержать наши функции.

Давайте установим файл, который будет содержать функции:

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

Теперь давайте установим параметры, которые мы будем использовать, чтобы указать DataStoreFactory , какой файл использовать, и указать, что нам нужно хранить пространственный индекс при создании нашего хранилища данных :

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

Давайте создадим DataStoreFactory , используя только что созданные параметры, и используем эту фабрику для создания хранилища данных :

ShapefileDataStoreFactory dataStoreFactory
  = new ShapefileDataStoreFactory();

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

6. Запись в шейп-файл

Последний шаг, который нам нужно сделать, – это записать наши данные в шейп-файл . Чтобы сделать это безопасно, мы собираемся использовать Транзакцию интерфейс , который является частью GeoTools API.

Этот интерфейс дает нам возможность легко фиксировать наши изменения в файле . Он также предоставляет способ выполнить откат неудачных изменений, если возникнет какая-либо проблема во время записи в файл:

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

SimpleFeatureSource используется для чтения функций, а SimpleFeatureStore используется для доступа на чтение/запись. В документации GeoTools указано, что использование метода instanceof для проверки возможности записи в файл является правильным способом сделать это.

Этот шейп-файл позже можно открыть с помощью любого средства просмотра ГИС, которое поддерживает шейп-файл .

7. Заключение

В этой статье мы рассмотрели, как мы можем использовать библиотеку GeoTools для выполнения некоторых очень интересных геопространственных работ.

Хотя пример был простым, его можно расширить и использовать для создания богатых шейп-файлов для различных целей.

Мы должны иметь в виду, что GeoTools – это динамичная библиотека, и эта статья просто служит основным введением в библиотеку. Кроме того, GeoTools не ограничивается созданием только векторных типов данных – он также может использоваться для создания или работы с растровыми типами данных.

Полный пример кода, использованного в этой статье, вы можете найти в нашем проекте GitHub . Это проект Maven, поэтому вы должны иметь возможность импортировать его и запустить как есть.