Как создать geojson файл
Преобразование и генерация данных GeoJSON и TopoJSON
каталог
1.1 GeoJSON
GeoJSON - это формат данных, используемый для описания геопространственной информации. GeoJSON не является новым форматом, и его грамматическая спецификация соответствует формату JSON, за исключением того, что его имя стандартизировано и специально используется для представления географической информации.
Внешний слой GeoJSON - это отдельный объект. Этот объект может представлять:
Omet геометрия;
② Функция;
Collection Коллекция функций (FeatureCollection);
Самый внешний GeoJSON может содержать множество подобъектов, каждый объект GeoJSON имеет атрибут типа, указывающий тип объекта, значение типа может быть: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, GeometryCollection, Feature , FeatureCollection
1.2 TopoJSON
TopoJSON является расширенной формой GeoJSON, закодированной в топологии, и был разработан Майком Бостоком, автором D3. По сравнению с GeoJSON, который напрямую использует геометрию, такую как Polygon и Point, для представления графики, каждая геометрия в TopoJSON формируется путем интеграции общих ребер (называемых дугами).
TopoJSON устраняет избыточность и уменьшает размер файла на 80%.
2.1 Векторизация
Процесс векторизации относительно прост, в основном новая база геоданных → Новый набор классов данных → Новый класс объектов → Запустите операцию векторизации. Те, кто не векторизован, могут использовать Baidu.
2.2 Экспорт данных в формате shp
Щелкните правой кнопкой мыши слой целевого класса объектов → Данные → Экспорт данных, как показано ниже:
Выберите тип экспорта и целевой путь, просто экспортируйте
2.3 Конвертировать данные shp в GeoJSON или TopoJSON
Выберите файл формата .shp, чтобы открыть
Откройте экспортированные данные JSON в редакторе, который вы увидите после форматирования:
На данный момент процесс производства данных GeoJSON завершен, и данные результатов можно скопировать в проект и использовать. Надеюсь, это поможет вам.
GeoJSON – это расширение формата данных JSON, которое служит для передачи геоданных. Эта утилита позволяет сохранять информацию о географических объектах в формате GeoJSON и отрисовывать их в слое поверх карты. Чтобы добавить данные GeoJSON на карту, вызовите метод addLayerToMap() . Чтобы удалить их, вызовите метод removeLayerFromMap() . Также можно добавлять и удалять отдельные географические объекты, вызывая методы addFeature() и removeFeature() и передавая им объекты GeoJsonFeature . Для доступа к географическим объектам используется метод getFeatures() , возвращающий итерируемый массив всех объектов GeoJsonFeature , добавленных в слой.
Можно задать стили по умолчанию, которые будут применяться к географическим объектам перед добавлением в слой. Для этого вызовите метод getDefaultPointStyle() , getDefaultLineStringStyle() или getDefaultPolygonStyle() и задайте параметры стиля. Вы также можете задать стиль для отдельного объекта GeoJsonFeature , вызвав для него метод setPointStyle() , setLineStringStyle() или setPolygonStyle() и передав нужный объект с параметрами стиля.
Как добавить слой GeoJsonLayer на карту
Чтобы добавить слой GeoJson на карту, сначала необходимо создать экземпляр класса GeoJsonLayer. Это можно сделать двумя способами.
Для импорта данных из объекта JSONObject вам понадобятся:
- объект GoogleMap для отрисовки слоя;
- объект JSONObject , содержащий данные GeoJSON, которые нужно добавить в слой.
Kotlin
Для импорта данных из локального файла GeoJSON вам понадобятся:
- объект GoogleMap для отрисовки слоя;
- локальный файл ресурсов, содержащий данные GeoJSON;
- объект Context , необходимый, чтобы открыть локальный файл ресурсов.
Kotlin
После создания объекта GeoJsonLayer вызовите метод addLayerToMap() , чтобы добавить импортированные данные на карту.
Kotlin
Как удалить слой GeoJsonLayer
Предположим, что вы добавили этот слой:
Kotlin
Чтобы очистить GeoJsonLayer, вызовите метод removeLayerFromMap() .
Kotlin
Как добавить или удалить объект GeoJsonFeature
Географический элемент в GeoJSON имеет тип feature. Он содержит геометрические данные и элемент свойства, а также может содержать ограничивающий прямоугольник или идентификатор.
Вы можете создать объекты GeoJsonFeature по отдельности и добавить их в слой GeoJsonLayer .
Предположим, что вы создали географический объект, который содержит точку с координатами 0, 0, имеет одну запись в свойствах и не имеет ограничивающего прямоугольника.
Kotlin
Чтобы добавить этот географический объект в слой, вызовите метод addFeature() и передайте ему этот объект.
Kotlin
Чтобы удалить объект после того, как он был добавлен в слой, вызовите метод removeFeature() и передайте ему этот объект.
Kotlin
Доступ к элементам GeoJsonFeature и их свойства
Чтобы обратиться к любому объекту GeoJsonFeature, добавленному в слой, вызовите метод getFeatures() для созданного вами объекта GeoJsonLayer . Будет возвращен итерируемый массив объектов GeoJsonFeatures , которые можно обработать с помощью цикла for-each, как показано ниже.
Kotlin
С помощью методов hasProperty() и getProperty() в сочетании с методом getFeatures() вы можете проверить, есть ли у каждого сохраненного объекта определенное свойство, и получить к нему доступ, если оно существует.
Kotlin
События кликов по фигурам GeoJSON
С помощью метода GeoJsonLayer.OnFeatureClickListener() можно прослушивать события кликов по геометрическим объектам на карте. В приведенном ниже примере кода реализовано сохранение названия объекта на карте при клике по этому объекту.
Kotlin
Как настроить стиль для GeoJsonLayer и GeoJsonFeature
Для слоя GeoJsonLayer можно выбрать стили по умолчанию или определить стиль для его отдельных элементов.
Стили по умолчанию
В слое GeoJsonLayer можно устанавливать стили по умолчанию для любых точек, ломаных линий и многоугольников, которые добавляются к слою. Стили по умолчанию применяются только в том случае, если вы не установили стиль для каких-либо геометрических компонентов элемента. Все изменения, выполненные для стиля по умолчанию, будут отражены во всех элементах, которые используют этот стиль.
Ниже приведены инструкции по настройке стиля по умолчанию.
- Получите соответствующий объект стиля по умолчанию. Это может быть один из следующих объектов: GeoJsonPointStyle , GeoJsonLineStringStyle или GeoJsonPolygonStyle .
- Примените нужные параметры к стилю.
Например, в приведенном ниже примере кода показано, как изменить стиль по умолчанию для точек. В результате точки станут перетаскиваемыми и у них появятся название и текстовый фрагмент.
Kotlin
Стили для конкретных объектов GeoJsonFeature
Вы также можете задавать стиль для отдельных объектов в слое. Чтобы применить стиль к объекту GeoJsonFeature , выполните следующие действия:
- Создайте нужный объект стиля ( GeoJsonPointStyle , GeoJsonLineStringStyle или GeoJsonPolygonStyle ).
- Примените желаемые параметры к стилю.
- Передайте объект стиля нужному методу объекта GeoJsonFeature (это может быть метод setPointStyle() , setLineStringStyle() или setPolygonStyle() ).
В приведенном ниже примере кода показано, как задать красный цвет для ломаных линий в объекте GeoJsonFeature .
Kotlin
Демонстрационное приложение
Пример импорта файла GeoJSON из указанного URL и создания слоя с помощью этого файла представлен в коде GeoJsonDemoActivity демонстрационного приложения из библиотеки утилит. В руководстве по настройке рассказывается, как запустить демонстрационное приложение.
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Конвертирует объекты в формат JSON или GeoJSON. Поля, геометрия и пространственная привязка объектов конвертируется в соответствующее представление JSON и записываются в файл с расширением .json или .geojson .
Использование
Если вы хотите, чтобы JSON-представление в выходном файле было более понятным, можно использовать форматирование. Выходной файл будет отформатирован с использованием пробелов, табуляторов и переходов на новые строки, что улучшит его читаемость. Форматированный JSON может быть удобен для разработки приложений и тестирования. Однако не рекомендуется использовать форматирование в реальных приложениях, поскольку все пробелы не являются необходимыми и игнорируются обработчиками JSON. Кроме того, форматированный JSON занимает значительно больше места, чем неформатированный, и размер файла будет больше, чем соответствующее представление JSON. Это может повлиять на производительность приложения.
Конвертация не поддерживает соединения, связи и вложения объектов.
Для конвертации поднабора объектов из класса объектов или слоя используйте инструменты Выбрать в слое по атрибуту или Выбрать в слое по расположению и выберите поднабор объектов для конвертации перед использованием инструмента Объекты в JSON .
Используйте параметр Выходные данные в GeoJSON ( geoJSON='GEOJSON' в Python) для создания файла .geojson , который соответствует спецификации GeoJSON. Значением выходного формата по умолчанию является Esri JSON.
Если в качестве выходного файла указан файл GeoJSON, у вас есть возможность спроецировать входные объекты в систему координат WGS 1984, которая является стандартом для спецификации GeoJSON. При необходимости будет применено географическое преобразование по умолчанию. Если опция не используется, выходной файл GeoJSON будет содержать тег crs , который используется в некоторых приложениях для определения системы координат. Этот тег не поддерживается полностью в спецификации GeoJSON.
В выходных данных инструмента будут только видимые атрибутивные поля входных данных. Чтобы включить все поля, их нужно сделать видимыми. Кроме того, вы можете использовать параметр Использовать псевдонимы полей , чтобы в выходных данных вместо имен полей использовались псевдонимы.
Для начала работы нам понадобятся две утилиты ogr2ogr и topojson . ogr2ogr входит в состав GDAL — библиотеки и набора утилит для работы с гео-данными. topojson — небольшая утилита, написанная на JavaScript и работающая на node.js.
Установить GDAL (и, соответственно, ogr2ogr ) на Mac OS можно, например, через MacPorts:
Под Linux тоже есть соответствующий пакет:
Ребятам с Windows я не помогу. Где-то на сайте проекта должен быть нужный архив. В комментарии приглашаются знающие люди.
Вторая утилита ставится через npm (не забудьте сначала установить node.js):
Всё, теперь можно приступать к работе.
Вся суть любой карты — это данные. Не будет данных, нечего будет рисовать. Я рекомендую данные Natural Earth из-за их доступности и открытости. Итак, идём в раздел 1:10m, Cultural и скачиваем карту с делением по странам (первый раздел, Admin 0 — Countries, любая ссылка).
Скачали, распаковали. Теперь с этим добром нужно что-то делать, данные-то в формате Shapefile. Для преобразования данных в читаемый вид нам и понадобится ogr2ogr — утилита, которая преобразует данные из одного векторного формата в другой. У неё огромное количество различных параметров, но я облегчу вам задачу.
После вызова этой команды должен появиться файл countries.json , содержащий те же данные, но в формате GeoJSON. Размер файла, конечно, не маленький — 24 Мб. Но не стоит отчаиваться: для работы понадобится его более оптимизированный собрат — TopoJSON.
В результате имеем файл размером 2.3 Мб, с ним и будем работать. Этот размер можно ещё значительно уменьшить, но об этом я расскажу чуть позже.
Начнём с создания новой страницы:
Теперь можно открывать всё это в браузере. Подойдёт любой статический сервер. Например, в PhpStorm, который я использую, можно просто нажать на файл правой клавишей и выбрать «Открыть в браузере» — выбранный файл отобразится с помощью небольшого встроенного в IDE сервера.
Создаём элемент <svg> размером с окно, в котором и будет происходить вся отрисовка. Для этого заменяем комментарий на подходящий код:
Эта инструкция создаёт html-элемент <svg> , добавляет его к <body> и прописывает подходящие размеры в атрибуты width и height .
Пришла пора загрузить данные. Дописываем в конец:
Я думаю, тут не надо ничего объяснять.
Теперь можно отобразить данные!
На самом деле это я быстро набросал, чтобы было что показать. Теперь будем постепенно менять, приводя к виду, который на самом деле хочется получить.
После каждого логического куска поста есть две ссылки: на результат, который должен был получиться, и на написанный мной код. Первые две можете наблюдать под картинкой чуть выше. Если вдруг что-то не получается, всегда можно подсмотреть или даже скопировать мою версию.
Пока не начинаешь рисовать карту, даже не задумываешься, какое огромное количество проекций придумали люди, чтобы покрасивее отобразить объёмную землю на плоской бумаге. Меркатор, Winkel Tripel, Aitoff, Dymaxion, проекция Гуда… Их десятки, если не сотни. В контексте d3 проекция — это просто функция, которая переводит географические координаты (широту и долготу) в координаты на экране.
На картинке выше используется Меркатор. Это можно увидеть и в коде.
Вынесем код создания проекции в самый верх и поместим проекцию в отдельную переменную, она нам ещё пригодится.
Код отрисовки карты чуть поменялся и стал ссылаться на новую переменную.
Как, может быть, вы уже заметили, я заменил Меркатора на более аккуратную Winkel Tripel (именно эту проекцию использует National Geographic для своих изданий). К сожалению, проекция не входит в стандартную поставку d3, поэтому придётся подключить ещё отдельный плагин с её определением.
Обновляем страницу и смотрим на новую картинку.
Возвращаемся к данным. Помните, что мы преобразовали наши данные в компактный TopoJSON? Перед отрисовкой эти данные всё равно придётся преобразовать обратно в GeoJSON, для этого у нас и подключена библиотека TopoJSON, посмотрите в заголовке нашего html.
В переменной countries теперь содержится массив с описанием стран в формате GeoJSON. Нарисуем их с помощью раздельных элементов <path> , благо d3 позволяет сделать это быстро и просто.
Создаём группу (элемент <g> ), которая очень пригодится нам в будущем. Это нужно вставить сразу после объявления переменной svg .
Заменяем код, ответственный за рисование.
Если вы ещё не знаете, что делает enter c выборкой из selectAll , то быстренько сходите и восполните этот пробел.
Переменная path в последней строчке — это функция, которая переводит описание страны из GeoJSON в строку, подходящую для отображения в svg. Её можно объявить в самом верху, сразу после объявления проекции.
Обновляем страницу (Результат, Исходники). Теперь границы государств стали более различимыми. Сделаем их ещё более видимыми с помощью css. Добавим в заголовок страницы блок <style> :
Следующий этап. Подсветим водные пространства синим. Для этого добавляем сразу после создания группы элемент <path> , который будет отвечать за фон.
Добавим также стиль фона к нашему css вверху документа.
Теперь добавим координатную сетку на фон.
И стиль для сетки:
И последний штрих — граница карты, просто для красоты. Создаётся точно так же, как и фон, разве что стиль другой.
Пришла пора добавить интерактива к карте. Но для начала разместим карту по центру и растянем на весь экран.
Для растягивания проекции нужно указать параметр scale , который по-умолчанию равен 150. К сожалению, все соотношения меняются от проекции к проекции, поэтому просто посчитаем нужные параметры для нашей. Для этого в инспекторе браузера нужно глянуть ширину и высоту элемента path , соответствующего фону. В случае Winkel Triple ширина равна 772, а высота — 472.
Максимальное увеличение, при котором карта будет помещаться на экран, по горизонтали равно 150 / 772 * width , по вертикали — 150 / 472 * height . Выбираем меньшее из двух.
Перемещаем проекцию в центр:
Всё, теперь можно добавлять интерактив. Как и положено, в таких библиотеках уже много всего придумано и реализовано за вас, остаётся только вызвать нужную функцию в нужный момент.
Создаём объект behavior.zoom , который будет отвечать за отслеживание событий:
Присоединяем созданный объект к нашему элементу <svg> :
И пишем обработчик для события zoom .
В d3 параметры события сохраняются в специальном объекте d3.event , в случае события zoom нас интересуют два параметра: translate — смещение карты и scale — текущее увеличение. После получения этих параметров мы накладываем ограничение на смещение, чтобы пользователь не мог сдвинуть карту дальше её границ. Затем мы записываем новое смещение обратно в объект zoom : без этого он будет продолжать считать, что текущее смещение другое и сообразно обрабатывать новые события от мыши. И последнее действие — применить новые параметры смещения и увеличения к карте: нужно же, чтобы картинка менялась соответственно нашим действиям.
Кстати, именно для правильной работы масштабирования мы и создавали элемент <g> выше. Атрибут transform не работает с элементом <svg> .
Идём дальше. Добавим к нашей карте немножко больше данных. Я создавал карту посещённых стран и городов, о чём и буду рассказывать. Я думаю, некоторые идеи можно применить и для других целей и наборов данных.
Такие совсем специфические данные, как список посещённых стран, взять негде, их придётся создавать самостоятельно. Я для этих целей создал файл data.json в таком формате:
Загружаем данные из data.json сразу после загрузки карты и добавляем правильный фон к странам.
В d3, если в методы attr и style вторым параметром передать функцию, то значения атрибутов и стилей соответственно будут браться из результатов вызова этой функции. Первым параметром передаётся значение элемента массива, ранее заданного с помощью метода data .
Остаётся добавить массив констант с вариантами цвета фона где-нибудь в начале файла:
Запускаем и видим, что ничего не поменялось (Результат, Исходники). На самом деле причина проста: в файле world.json нет информации о кодах стран. Ошибка исправляется передачей дополнительного параметра в вызов topojson . Перегенерировать world.json нужно такой командой:
Теперь можно нарисовать города. Для этого сразу после кода, ответственного за рисование стран, добавляем код для рисования городов:
Обратите внимание, что координаты в path передаются в формате [широта, долгота] .
Не забываем в начале объявить массив cities :
И добавить стиль для городов:
Да, точки для городов хотелось бы сделать поменьше. Добавляем правило рисования точек в path :
А ещё неплохо было бы сделать так, чтобы размер точек менялся с масштабом. Значит, добавляем код в конец функции onZoom .
Теперь добавим подпись для объектов при наведении мышкой. Для этого сначала создаём в DOM элемент <div> с классом tooltip .
И создаём соответствующий ему стиль.
Осталось написать обработчики событий мыши mousemove и mouseout . Для этого в операцию создания стран добавляем новые инструкции (новый код начинается с вызова метода on ).
Из-за того, что метод on вызван после вызова enter , события вешаются на каждый элемент <path> в отдельности, а в параметры передаётся соответствующий элемент из массива countries .
Метод d3.mouse возвращает текущие координаты мыши относительно контейнера, переданного в параметрах. В нашем случае это элемент <svg> . Дальше все просто: записываем в tooltip нужное содержимое и устанавливаем стили left , top и display .
В обработчике события mouseout прячем наш элемент с подписью. И всё работает как надо!
Добавим аналогичный код для отображения подписей к городам.
Тут всё абсолютно аналогично.
Некоторые из вас, должно быть, заметили, что, например, Франция имеет территорию в Южной Америке, которая тоже подсвечивается. А от этого хочется избавиться, ведь нас там не было. Чтобы получить правильный результат, можно воспользоваться другим набором данных с Natural Earth. Снова идём в раздел 1:10m, Cultural и скачиваем карту с делением по subunits (Admin 0 — Details, Download map subunits).
Если мы просто заменим файл с исходными данным, то быстро заметим, что кроме Франции изменениям подверглись ещё несколько стран. Например, Бельгия оказалась разделена на три части: Фландрию, Валлонию и Брюссель, да и на Великобритании тоже появились границы между Англией, Шотландией и Уэльсом. Получается, чтобы получить желаемый результат, придётся составить карту из двух источников.
Возьмём Францию из ne_10m_admin_0_map_subunits . Обратите внимание на параметр -where , который накладывает нужные ограничения на выборку.
Вторая часть выборки:
Теперь собираем это всё в один TopoJSON-файл.
Обратите внимание на то, как изменился вызов topojson , особенно параметр id-property . Все дело в том, что атрибут ADM_A3 содержит код страны, то есть у всех частей Франции код будет один и тот же. Поэтому для неё нужен другой атрибут в качестве идентификатора. Атрибуты в параметре id-property берутся в обратном порядке: сначала утилита пытается взять SU_A3 , а в случае, если его нет, берет предыдущий, то есть ADM_A3 .
Теперь для правильной отрисовки нужно добавить в массив countries новые элементы.
Конструкция push.apply добавляет все элементы одного массива в другой. Более подробно про this , call и apply можно почитать в моей старой статье про ООП в JavaScript (раздел «Ключевое слово this»).
Следующее пожелание: крупные страны, например, США и Россию, поделить на штаты и субъекты соответственно. Для этого нам понадобится новый источник данных. Снова идём на привычный адрес и скачиваем файл из раздела Admin 1 — States, Provinces.
Пересобираем файлы, не забыв предварительно удалить старые ( org2org отказывается перезаписывать файлы, если вы ещё не заметили).
Так же как и раньше, добавляем новые данные для рисования в массив countries .
Вообще говоря, подсветку штатов и субъектов я писал отдельно, но можно просто добавить нужные идентификаторы в файл data.json .
В файлах, скачанных с Natural Earth, есть множество дополнительных данных, не только форма границ и код страны. Большая часть этих данных лежит в файле .dbf , который представляет собой файл базы данных dBase. И если у вас есть просмотрщик для этого формата, то можете смело его открывать. Если же нет, то можно воспользоваться Online-конвертером из dbf в csv. Я использовал именно этот способ. После конвертации сsv-файл можно открыть LibreOffice или же Microsoft Excel.
ogr2ogr тоже копирует все данные из файлов атрибутов внутрь результирующего файла, а topojson может копировать некоторые необходимые атрибуты в файл TopoJSON. Вот таким образом можно добавить атрибут NAME , который содержит английское название объекта:
Теперь можно использовать значение поля, например, для отображения названий непосещённых стран. Вот эту строчку нужно заменить в обработчике события mousemove для стран:
Последний нерешенный вопрос: размер файла с картой. После всех наших манипуляций он стал весить 2.6 Мб, что, согласитесь, несколько многовато. topojson предоставляет несколько параметров для оптимизации. Один из них так и называется — simplify . Для получения оптимального результата придётся, конечно, немного поэкспериментировать с величиной, в нашем же случае вполне подойдёт 1e-6 .
Получившийся файл имеет размер 444 Кб и всё ещё приемлемую детализацию.
Спасибо Mike Bostock за такую прекрасную библиотеку. И отдельное спасибо ему же за прекрасные записи в блоге, некоторые идеи из которых перекочевали в этот пост.
Читайте также: