Введение
Привет! Если тебе пришлось на проекте столкнуться с геоданными, но ты ещё не знаком с этой областью или ищешь короткое введение в работу с ними — эта статья для тебя.
Я не являюсь экспертом в ГИС (геоинформациооных системах); эта статья подводит итог тому, что я сам узнал для базовой работы с геоданными.
Подготовоительная информация
Эллипсоид — математическая модель поверхности Земли
Для расчетов нам нужна некоторая поверхность, на которой мы будем отмечать точки. Математической моделью поверхности Земли (геоида) выступают эллипсоиды.
Суть в том, чтобы выбрать эллипсоид, максимально «обтекающий» реальный геоид и сводящий отклонения от его поверхности к минимуму.
Эллипсоид определяется следующими параметрами:
- Большая (экваториальная) полуось
- Малая (полярная) полуось
Из этих параметров можно вывести еще один — коэффициент сжатия: отношение разности большой и малой полуосей к большой полуоси.
Координаты и Coordinate Reference System (CRS)
Точки в пространстве можно задать некоторыми координатами. Они бывают:
- Эллипсоидальными (географическими/геодезическими) — задаются угловыми величинами lat, lon, отражают положение точек на эллипсоиде. Выражаются в градусах или радианах.
- Прямоугольными (спроецированными/метрическими) — задаются координатами x, y на плоскости (картографической проекции), выражаются в метрах или футах.
Чтобы координаты точно отражали положение точек на заданной поверхности, их необходимо «привязать» к ней с помощью системы координат.
CRS (Coordinate Reference System) — это система координат, которая однозначно задаёт, как числа (координаты) интерпретировать как реальные точки на Земле, а также определяет единицы измерения.
Координаты из разных систем отражают разные точки в пространстве.
WGS 84
WGS 84 — международный стандарт, определяющий параметры эллипсоида, датум (набор геопараметров) и эллипсоидальную систему координат.
В геоинформационных системах именно WGS 84 используется как «система координат по умолчанию», если не выбрана более специализированная.
На эту тему есть доклад FOSS4GE 2024 | WGS 84: I don’t know, I don’t care, в котором докладчик объясняет, что такое WGS 84, с какой точностью можно проводить расчеты с его помощью и на какие нюансы при работе с ним часто не обращают внимания.
SRID
SRID (Spatial Reference System Identifier) — это числовой идентификатор, указывающий на конкретную систему координат и проекцию, включая информацию об эллипсоиде, датуме и единицах измерения.
Например, SRID WGS 84 в EPSG (реестре геодезических данных) — 4326.
Согласно реестру, для WGS 84 принята двумерная эллипсоидальная система координат с градусом в качестве единицы измерения.
Simple Features Standard
SFS/SFSQL (Simple Features Standard/Simple Features for SQL) — это стандарт, разработанный Open Geospatial Consortium (OGC), который определяет:
- Набор геометрических типов (Point, LineString, Polygon, MultiPoint и т. д.)
- Форматы хранения и обмена (WKT — Well-Known Text, WKB — Well-Known Binary)
- Набор пространственных операций и функций (ST_Contains, ST_Intersects, ST_Buffer и т. д.)
Ознакомиться можно по ссылке.
В следующих разделах статьи мы увидим, как этот стандарт применяется.
Well-known text (WKT)
WKT — текстовый формат для описания геоданных.
Пример: POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))
Примеры других географий с картинками есть на википедии.
Удобный инструмент для визуализации WKT на карте https://wktmap.com/
GeoJSON
О спецификации
GeoJSON — это спецификация, которая задает правила передачи геопространственных данных в формате JSON и включает в себя 7 геометрических типов из SFSQL: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, GeometryCollection.
Со спецификацией можно ознакомиться по ссылке.
Общая структура объектов GeoJSON
GeoJSON может передавать следующие типы:
- Geometry — определенное место в пространстве
- Feature — место в пространстве (Geometry) с набором свойств (произвольные key-value пары)
- FeatureCollection — набор Feature
Чтобы парсер понимал, с каким типом объекта он работает, GeoJSON-объекты обязательно содержат поле type
.
{
"type": "FeatureCollection", // FeatureCollection: коллекция Feature
"features": [ // массив Feature-объектов
{ // Feature #1
"type": "Feature", // Тип объекта — Feature
"properties": { // Свойства Feature
"name": "Точка интереса"
},
"geometry": { // Geometry вложена в Feature
"type": "Point", // Тип геометрии — Point
"coordinates": [37.6173, 55.7520] // Координаты точки (Position)
}
},
{ // Feature #2
"type": "Feature",
"properties": {
"name": "Улица"
},
"geometry": { // Geometry вложена в Feature
"type": "LineString", // Тип геометрии — LineString
"coordinates": [ // Массив Position, задающий ломаную линию
[37.6173, 55.7520],
[37.6200, 55.7550],
[37.6225, 55.7540]
]
}
}
]
}
Geometry
Geometry — это базовый объект, описывающий форму и положение пространственного элемента. Все объекты Geometry имеют два обязательных поля:
-
type — строка, задающая тип геометрии. Стандартные значения:
- Point
- MultiPoint
- LineString
- MultiLineString
- Polygon
- MultiPolygon
- GeometryCollection
-
coordinates — Массив чисел или вложенных массивов (в спецификации они называются Position), описывающий координаты в 2D или 3D.
Вот пример объекта типа Polygon
{
"type": "Polygon",
"coordinates": [
[
[30.0, 10.0],
[40.0, 40.0],
[20.0, 40.0],
[30.0, 10.0]
]
]
}
Position
Позиция — это набор координат в системе WGS 84.
Координаты точки составляют позицию.
Набор позиций составляет более сложные сущности вроде LineString или MultiPoint
Из этих объектов могут строиться еще более сложные сущности вроде Polygon и MultiPolygon.
Типы Geometry
Название геометрии | Что из себя представляет | Какой набор позиций содержит | Примеры из реальной жизни |
---|---|---|---|
Point | Одна отдельная точка | Одна Position | Отметка местоположения кафе или дерева на карте |
MultiPoint | Набор независимых точек | Массив Position | Расположение всех автобусных остановок в городе |
LineString | Ломанная линия, соединяющая точки последовательно | Упорядоченный массив Position | Маршрут дороги или пешеходная тропа |
MultiLineString | Коллекция нескольких ломаных линий | Массив упорядоченных массивов Position | Сеть железнодорожных путей или электроснабжения |
Polygon | Замкнутый контур (многоугольник), может содержать «дырки» | Массив колец: каждый — массив Position (первое и последнее совпадают) | Граница города, форма озера или парка |
MultiPolygon | Набор нескольких многоугольников | Массив массивов колец: массивы массивов Position | Архипелаг островов или разбросанные парки |
GeometryCollection | Коллекция различных объектов Geometry | Не имеет coordinates ; содержит массив объектов Geometry в geometries |
Смешанные объекты: здание (Polygon), входы (Point) и подходящие дорожки (LineString) |
Изображения
Point GeoJSON

MultiPoint GeoJSON

LineString GeoJSON

MultiLineString GeoJSON

Polygon GeoJSON

MultiPolygon GeoJSON

GeometryCollection GeoJSON (другой объект)

Отображение GeoJSON на карте
Отображать и редактировать GeoJSON на карте можно с помощью сервиса geojson.io
Java
JTS
JTS Topology Suite — библиотека для работы с объектами из SFSQL в Java.
Библиотека предоставляет не только структуру объектов, но и операции над ними: расчет расстояния, площадей, пространственных предикатов (покрытие/пересечения и т. д.). (ссылка на документацию).
JTS оперирует плоской (евклидовой) геометрией, поэтому входные геоданные нужно заранее спроецировать в плоскую систему координат.
Для проекций можно воспользоваться библиотеками org.locationtech.proj4j:proj4j
и org.locationtech.proj4j:proj4j-epsg
JTS & GeoJSON
Пакет org.locationtech.jts.io:jts-io-common
предоставляет классы для сериализации/десериализации объектов GeoJSON и JTS.
Пример использования:
public class Main {
public static void main(String[] args) {
String geoJson = """
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [74.59, 42.87]
},
"properties": {
"name": "Bishkek"
}
}
""";
GeoJsonReader reader = new GeoJsonReader();
try {
// Парсим GeoJSON → JTS Geometry
Geometry geometry = reader.read(geoJson);
System.out.println("Parsed JTS geometry: " + geometry);
System.out.println(geometry.getSRID());
} catch (ParseException e) {
// Обрабатываем checked-исключение...
}
}
}
Output
Parsed JTS geometry: POINT (74.59 42.87)
4326 // WGS 84 — SRID, используемый в GeoJSON.
JTS & Hibernate Spatial
Hibernate Spatial позволяет использовать объекты JTS для хранения геоданных в СУБД. Помимо прямой поддержки JTS-объектов в полях сущностей (Entity-классов), он обеспечивает интеграцию с пространственными диалектами (например, PostGIS) и набором готовых пространственных функций.
Ознакомиться с документацией можно по ссылке.
PostgreSQL и PostGIS
PostGIS — это расширение для PostgreSQL, реализующее поддержку объектов геометрии и географии по спецификации OGC Simple Features (SFS) и предоставляющее набор функций для работы с этими объектами.
Полный список поддерживаемых типов геометрий доступен по ссылке.
Пространственные функции PostGIS
В PostGIS доступен набор функций для проверки пространственных отношений — вхождения, пересечения, равенства и др.
Описание с наглядными примерами и SQL-запросами можно найти в документации.
Geometry vs Geography
PostGIS позволяет работать как с плоской геометрией в произвольных проекционных CRS (тип geometry), так и с геодезическими координатами на эллипсоидах (тип geography).
Параметр | Geometry | Geography |
---|---|---|
Модель пространства | Плоская | Эллипсоид |
Кратчайшее расстояние между двумя точками | Прямая | Дуга на эллипсоиде |
Система координат | Любой SRID, включая локальные CRS | Только эллипсоидальные |
Производительность | Быстрее: вычислления на плоскости выполняются быстро | Медленнее: расчёты по эллипсоиду дороже по ресурсам. |
Юзкейсы | Локальные и региональные задачи в спроецированных CRS. | Глобальные данные в широте/долготе. |
Расстояние между двумя точками
Для демонстрации разницы между geography и geometry посчитаем расстояние по прямой между Бишкеком (lat 42.87, lon 74.59) и Караколом (lat 42.49, lon 78.39). Согласно калькулятору, расстояние между точками 315 км.
Geography
Посчитаем расстояние на эллипсоиде WGS 84
SELECT
ST_Distance(
ST_SetSRID(ST_MakePoint(74.5698, 42.8746), 4326)::geography,
ST_SetSRID(ST_MakePoint(78.3933, 42.4986), 4326)::geography
) AS distance_meters;
Output
distance_meters |
---|
316094.80038898 |
Получили 316 км.
Geometry
А теперь посмотрим на результат на плоскости.
Спроецируем WGS 84 в WGS 84 / Pseudo-Mercator — Spherical Mercator (EPSG:3857)
SELECT
ST_Distance(
ST_Transform(
ST_SetSRID(ST_MakePoint(74.59, 42.87), 4326), -- 4326 — SRID WGS 84
3857 -- 3857 — SRID WGS 84 / Pseudo-Mercator — Spherical Mercator
),
ST_Transform(
ST_SetSRID(ST_MakePoint(78.39, 42.49), 4326),
3857
)
) AS distance_meters;
Output
distance_meters |
---|
426909.7201568989 |
Получили отклонение на 110 км.
Чтобы получить более точные результаты, нужно подобрать подходящую CRS.
Для Кыргызстана такой является WGS 84 / UTM zone 43N (EPSG:32643)
Посчитаем в новой проекции
SELECT
ST_Distance(
ST_Transform(
ST_SetSRID(ST_MakePoint(74.59, 42.87), 4326),
32643
),
ST_Transform(
ST_SetSRID(ST_MakePoint(78.39, 42.49), 4326),
32643
)
) AS distance_meters;
Output
distance_meters |
---|
314242.10025156994 |
Получили корректный результат — 314 км.
Индексы
PostgreSQL умеет индексировать пространственные данные.
Подробное описание алгоритмов и внутренних структур индексов выходит за рамки этой статьи: в интернете уже есть качественные материалы на эту тему.
Вот некоторые из них:
Доклад Павла Кислова — Павел рассказывает как устроены пространственные индексы, когда их лучше использовать, приводит бенчмарки.
PostGIS intro workshop — как устроены пространственные индексы; как функции PostGIS работают с этими индексами.
Пример использования
Представим, что у нас есть 3 магазина и 2 службы доставки, которые работают в определенных областях.
Отметим их на карте:

Векторные слои: © GeoData Show.
Создадим и наполним таблицы
CREATE TABLE shop (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
geom GEOMETRY(Point, 4326) NOT NULL
);
CREATE TABLE delivery_area (
id SERIAL PRIMARY KEY,
service TEXT NOT NULL,
area GEOMETRY(Polygon, 4326) NOT NULL
);
INSERT INTO shop (name, geom) VALUES
('Магазин на Льва Толстого', ST_SetSRID(ST_MakePoint(74.595526, 42.863348), 4326)),
('Магазин на Киевской', ST_SetSRID(ST_MakePoint(74.593933, 42.875174), 4326)),
('Магазин на Московской', ST_SetSRID(ST_MakePoint(74.615718, 42.869289), 4326));
INSERT INTO delivery_area (service, area) VALUES
(
'ProКурьер',
ST_SetSRID(
ST_GeomFromText(
'POLYGON((
74.583778 42.859294,
74.604979 42.859294,
74.604979 42.878166,
74.583778 42.878166,
74.583778 42.859294
))'
),
4326
)
),
(
'БыстраяДоставка',
ST_SetSRID(
ST_GeomFromText(
'POLYGON((
74.578457 42.867032,
74.623518 42.867032,
74.623518 42.880115,
74.578457 42.880115,
74.578457 42.867032
))'
),
4326
)
);
Допустим, на бэкэнд пришли координаты пользователя POINT(74.600794 42.872347)
, и нам нужно отобразить ближайшие к нему магазины.

Векторные слои: © GeoData Show.
Запросим ближайшие магазины
SELECT
id,
name,
ST_Distance(
geom::geography,
ST_SetSRID(ST_MakePoint(74.600794, 42.872347), 4326)::geography
) AS dist_m
FROM shop
ORDER BY dist_m
LIMIT 3;
Output
id | name | dist_m |
---|---|---|
2 | Магазин на Киевской | 642.57083016 |
1 | Магазин на Льва Толстого | 1088.44452992 |
3 | Магазин на Московской | 1265.89776504 |
А теперь проверим, какие курьерские службы могут осуществить доставку клиенту
SELECT
id, service
FROM delivery_area
WHERE ST_Contains(
area,
ST_SetSRID(ST_MakePoint(74.600794, 42.872347), 4326)
);
Output
id | service |
---|---|
1 | ProКурьер |
2 | БыстраяДоставка |
Итог
В этой статье мы рассмотрели:
- Эллипсоид как модель Земли для географических расчетов и конкретную эллипсоидальную систему координат WGS 84.
- CRS и SRID — как однозначно задать систему координат на поверхности (плоскости/эллипсоиде).
- Стандарт Simple Features (SFA/SFS), который задаёт набор геометрий и операций над ними.
- GeoJSON как формат для передачи геоданных в JSON.
- Основные геометрии SFA (
Point
,LineString
,Polygon
и т. д.) на примере GeoJSON - Как работать с SFS-объектами в Java с помощью JTS, как получить JTS объекты из GeoJSON, как научить Hibernate работать с этими объектами.
- Возможности PostGIS и различие между типами
geometry
(плоскость) иgeography
(эллипсоид) на примере вычисления реального расстояния между двумя точками.
Спасибо за внимание! Подписывайтесь на мой Telegram канал чтобы не пропустить новые статьи.