Работа с WKT

WKT (Well-Known Text) — текстовый формат представления геометрических объектов, разработанный консорциумом Open Geospatial Consortium (OGC). Формат широко применяется в геоинформационных системах, базах данных и картографических платформах для хранения и обмена пространственными данными.

В отличие от GeoJSON, который использует структуру JSON, WKT представляет геометрию в виде строкового описания:

POINT (37.6173 55.7558)

или

LINESTRING (
  37.6173 55.7558,
  37.6200 55.7600,
  37.6250 55.7650
)

В проектах на основе Kepler.gl формат WKT часто встречается при работе с:

  • пространственными базами данных;
  • экспортом данных из GIS-систем;
  • выгрузками из PostGIS;
  • корпоративными геоинформационными платформами;
  • CSV-файлами, содержащими геометрию в текстовом виде.

Поддержка WKT в Kepler.gl

Kepler.gl ориентирован на работу с координатными данными и форматом GeoJSON. При загрузке таблиц приложение способно автоматически распознавать некоторые варианты геометрии, однако на практике данные WKT часто требуют предварительного преобразования.

Типичный набор данных может выглядеть следующим образом:

id name geometry
1 Москва POINT (37.6173 55.7558)
2 Казань POINT (49.1064 55.7961)
3 Омск POINT (73.3686 54.9914)

Здесь поле geometry содержит строку WKT.

После загрузки такого CSV-файла Kepler.gl воспринимает колонку как обычный текст, пока не будет выполнено преобразование в геометрический объект.


Основные типы геометрии WKT

POINT

Точка представляет одну координатную пару.

POINT (30 10)

Для географических данных:

POINT (37.6173 55.7558)

Структура:

POINT (longitude latitude)

Важно помнить, что порядок координат соответствует:

долгота широта

а не наоборот.


LINESTRING

Ломаная линия состоит из последовательности точек.

LINESTRING (
  30 10,
  10 30,
  40 40
)

Используется для:

  • дорог;
  • маршрутов;
  • рек;
  • линий связи;
  • транспортных путей.

POLYGON

Полигон описывает замкнутую область.

POLYGON (
  (
    30 10,
    40 40,
    20 40,
    10 20,
    30 10
  )
)

Первая и последняя точка должны совпадать.

Области применения:

  • административные границы;
  • земельные участки;
  • зоны покрытия;
  • районы городов.

MULTIPOINT

Набор точек.

MULTIPOINT (
  (10 40),
  (40 30),
  (20 20),
  (30 10)
)

MULTILINESTRING

Набор линий.

MULTILINESTRING (
  (
    10 10,
    20 20
  ),
  (
    15 15,
    30 15
  )
)

MULTIPOLYGON

Набор полигонов.

MULTIPOLYGON (
  (
    (
      30 20,
      45 40,
      10 40,
      30 20
    )
  ),
  (
    (
      15 5,
      40 10,
      10 20,
      5 10,
      15 5
    )
  )
)

Такие объекты часто встречаются при работе с государственными границами и архипелагами.


Установка библиотеки для работы с WKT

Для преобразования WKT в GeoJSON обычно используется библиотека Terraformer.

Установка:

npm install terraformer-wkt-parser

Либо:

yarn add terraformer-wkt-parser

Импорт:

import WKT from 'terraformer-wkt-parser';

Преобразование POINT в GeoJSON

Исходная строка:

const wkt = 'POINT (37.6173 55.7558)';

Преобразование:

import WKT from 'terraformer-wkt-parser';

const geojson = WKT.parse(wkt);

console.log(geojson);

Результат:

{
  type: 'Point',
  coordinates: [37.6173, 55.7558]
}

Такой объект уже может использоваться в слоях Kepler.gl.


Конвертация LINESTRING

Исходные данные:

const wkt = `
LINESTRING (
  37.6173 55.7558,
  37.6200 55.7600,
  37.6250 55.7650
)
`;

Преобразование:

const geojson = WKT.parse(wkt);

Результат:

{
  type: 'LineString',
  coordinates: [
    [37.6173, 55.7558],
    [37.6200, 55.7600],
    [37.6250, 55.7650]
  ]
}

Конвертация POLYGON

Исходная геометрия:

const wkt = `
POLYGON (
(
37.60 55.70,
37.70 55.70,
37.70 55.80,
37.60 55.80,
37.60 55.70
)
)
`;

Преобразование:

const geojson = WKT.parse(wkt);

Результат:

{
  type: 'Polygon',
  coordinates: [
    [
      [37.60, 55.70],
      [37.70, 55.70],
      [37.70, 55.80],
      [37.60, 55.80],
      [37.60, 55.70]
    ]
  ]
}

Обработка массива объектов

Чаще всего данные поступают в виде массива записей.

Исходный набор:

const data = [
  {
    id: 1,
    name: 'Москва',
    geometry: 'POINT (37.6173 55.7558)'
  },
  {
    id: 2,
    name: 'Казань',
    geometry: 'POINT (49.1064 55.7961)'
  }
];

Преобразование:

const preparedData = data.map(item => ({
  ...item,
  geometry: WKT.parse(item.geometry)
}));

Результат:

[
  {
    id: 1,
    name: 'Москва',
    geometry: {
      type: 'Point',
      coordinates: [37.6173, 55.7558]
    }
  },
  {
    id: 2,
    name: 'Казань',
    geometry: {
      type: 'Point',
      coordinates: [49.1064, 55.7961]
    }
  }
]

Формирование полноценного GeoJSON FeatureCollection

Для загрузки в Kepler.gl удобно создавать структуру GeoJSON.

Исходные данные:

const records = [
  {
    id: 1,
    city: 'Москва',
    wkt: 'POINT (37.6173 55.7558)'
  },
  {
    id: 2,
    city: 'Казань',
    wkt: 'POINT (49.1064 55.7961)'
  }
];

Преобразование:

const geojson = {
  type: 'FeatureCollection',
  features: records.map(item => ({
    type: 'Feature',
    properties: {
      id: item.id,
      city: item.city
    },
    geometry: WKT.parse(item.wkt)
  }))
};

Результат соответствует стандарту GeoJSON и может быть передан непосредственно в Kepler.gl.


Загрузка данных в Kepler.gl

После подготовки GeoJSON данные добавляются через действие addDataToMap.

Пример:

import {addDataToMap} from 'kepler.gl/actions';

dispatch(
  addDataToMap({
    datasets: {
      info: {
        label: 'Cities'
      },
      data: geojson
    }
  })
);

После загрузки Kepler.gl автоматически определяет тип геометрии и создаёт соответствующий слой.


Автоматическое преобразование WKT при импорте CSV

Нередко сервер возвращает CSV следующего вида:

id,name,geometry
1,Москва,"POINT (37.6173 55.7558)"
2,Казань,"POINT (49.1064 55.7961)"

После парсинга:

const parsedRows = rows.map(row => ({
  ...row,
  geometry: WKT.parse(row.geometry)
}));

Далее можно собрать GeoJSON:

const featureCollection = {
  type: 'FeatureCollection',
  features: parsedRows.map(row => ({
    type: 'Feature',
    properties: {
      id: row.id,
      name: row.name
    },
    geometry: row.geometry
  }))
};

Обработка ошибок при разборе WKT

Данные из внешних систем могут содержать повреждённую геометрию.

Пример:

POINT (37.61)

или

POLYGON (
  (
    10 10,
    20 20
  )
)

Для безопасной обработки используется конструкция:

function parseWKT(wkt) {
  try {
    return WKT.parse(wkt);
  } catch (error) {
    console.error('Ошибка разбора:', error);

    return null;
  }
}

Использование:

const geometry = parseWKT(record.geometry);

Фильтрация невалидных геометрий

Перед созданием GeoJSON полезно исключать ошибочные записи.

const features = records
  .map(item => {
    try {
      return {
        type: 'Feature',
        properties: item,
        geometry: WKT.parse(item.geometry)
      };
    } catch {
      return null;
    }
  })
  .filter(Boolean);

Работа с большими объёмами данных

При обработке десятков или сотен тысяч объектов следует учитывать стоимость преобразования WKT.

Неэффективный вариант:

render() {
  return data.map(item => WKT.parse(item.geometry));
}

Парсинг будет выполняться при каждом рендере.

Предпочтительный подход:

const parsedData = useMemo(
  () =>
    data.map(item => ({
      ...item,
      geometry: WKT.parse(item.geometry)
    })),
  [data]
);

Преобразование выполняется только при изменении исходного массива.


Преобразование WKT на сервере

Если объём данных велик, более рационально выполнять конвертацию на стороне сервера.

Пример для Node.js:

import WKT from 'terraformer-wkt-parser';

app.get('/api/cities', async (req, res) => {
  const rows = await db.query();

  const geojson = {
    type: 'FeatureCollection',
    features: rows.map(row => ({
      type: 'Feature',
      properties: row,
      geometry: WKT.parse(row.geometry)
    }))
  };

  res.json(geojson);
});

В этом случае клиент получает уже готовый GeoJSON.


Получение WKT из PostGIS

Очень распространённый источник WKT — база данных PostGIS.

Запрос:

SEL ECT
  id,
  name,
  ST_AsText(geom) AS geometry
FR OM cities;

Результат:

POINT (37.6173 55.7558)

Для получения GeoJSON непосредственно из базы:

SEL ECT
  id,
  name,
  ST_AsGeoJSON(geom) AS geometry
FR OM cities;

Такой вариант обычно быстрее и избавляет приложение от дополнительного преобразования.


Сравнение WKT и GeoJSON

Характеристика WKT GeoJSON
Формат Текстовая строка JSON
Читаемость Высокая Высокая
Размер Компактный Больше
Поддержка в GIS Отличная Отличная
Поддержка в Web Ограниченная Максимальная
Работа в Kepler.gl Через преобразование Нативная

Практические сценарии использования WKT в Kepler.gl

Визуализация данных из PostGIS

Типовой процесс:

  1. Получение геометрии через ST_AsText.
  2. Конвертация WKT в GeoJSON.
  3. Формирование FeatureCollection.
  4. Передача данных в Kepler.gl.
  5. Настройка слоёв и визуализации.

Отображение маршрутов

Источник данных:

LINESTRING (...)

После преобразования создаются линейные слои для отображения:

  • транспортных маршрутов;
  • логистических цепочек;
  • GPS-треков;
  • путей перемещения объектов.

Работа с административными границами

Источник:

MULTIPOLYGON (...)

После преобразования такие объекты используются для:

  • тематических карт;
  • геоаналитики;
  • визуализации территорий;
  • отображения зон ответственности.

Анализ точечных объектов

Источник:

POINT (...)

После конвертации возможно создание:

  • кластеров;
  • тепловых карт;
  • точечных слоёв;
  • агрегационных визуализаций.

Интеграция корпоративных GIS-систем

Многие корпоративные системы экспортируют геометрию именно в формате WKT. В подобных сценариях Kepler.gl выступает визуализационным слоем, а преобразование WKT в GeoJSON становится промежуточным этапом подготовки данных перед отображением на карте.