Трансформация geopath, geopoint, geoshape

Географическая визуализация в Vega и Vega-Lite строится вокруг преобразования пространственных данных в экранные координаты. Для этой задачи используются специализированные трансформации:

  • geopath
  • geopoint
  • geoshape

Они работают совместно с географическими проекциями (projection) и позволяют отображать:

  • карты;
  • маршруты;
  • геометрические фигуры;
  • координатные точки;
  • полигоны;
  • границы стран и регионов;
  • пользовательские геометрические объекты GeoJSON.

Географические данные в Vega

Vega использует несколько распространённых форматов:

Формат Назначение
GeoJSON Геометрические объекты
TopoJSON Оптимизированные карты
Latitude/Longitude Координаты точек
FeatureCollection Коллекция геообъектов

Типичный GeoJSON-объект:

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [37.6173, 55.7558]
  },
  "properties": {
    "name": "Москва"
  }
}

Роль projection

Все географические трансформации используют projection.

Без проекции Vega не знает, как перевести координаты Земли в координаты экрана.

Пример:

{
  "projections": [
    {
      "name": "myProjection",
      "type": "mercator"
    }
  ]
}

Поддерживаются десятки проекций:

Проекция Назначение
mercator Веб-карты
albers США
equalEarth Равновеликая карта
orthographic Глобус
naturalEarth1 Атласы
azimuthalEqualArea Полярные карты

Трансформация geopath

Назначение

geopath преобразует геометрические объекты GeoJSON в SVG path.

Именно эта трансформация используется для:

  • стран;
  • регионов;
  • контуров;
  • границ;
  • рек;
  • дорог;
  • полигонов.

Принцип работы

На вход подаётся геометрия:

{
  "type": "Polygon",
  "coordinates": [...]
}

На выходе получается:

M120,40L140,60L...

То есть строка SVG path.


Базовый пример geopath

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",

  "width": 800,
  "height": 500,

  "data": [
    {
      "name": "world",
      "url": "world.geojson",
      "format": {
        "type": "geojson"
      }
    }
  ],

  "projections": [
    {
      "name": "projection",
      "type": "mercator",
      "scale": 130,
      "translate": [400, 250]
    }
  ],

  "marks": [
    {
      "type": "shape",
      "from": {
        "data": "world"
      },

      "transform": [
        {
          "type": "geopath",
          "projection": "projection"
        }
      ],

      "encode": {
        "update": {
          "stroke": {
            "value": "#333"
          },
          "fill": {
            "value": "#d8e2dc"
          }
        }
      }
    }
  ]
}

Как работает geopath

Этап 1 — загрузка геометрии

{
  "type": "Polygon"
}

Этап 2 — применение projection

{
  "projection": "projection"
}

Этап 3 — генерация SVG path

M120,40L...

Этап 4 — рендеринг shape

{
  "type": "shape"
}

Параметры geopath

Параметр Описание
projection Используемая проекция
field Поле с геометрией

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

Иногда геометрия хранится во вложенном поле:

{
  "geometry": {
    "type": "Polygon"
  }
}

Тогда:

{
  "type": "geopath",
  "field": "datum.geometry",
  "projection": "projection"
}

geopath и TopoJSON

TopoJSON значительно компактнее GeoJSON.

Пример подключения:

{
  "data": [
    {
      "name": "countries",
      "url": "world-110m.json",
      "format": {
        "type": "topojson",
        "feature": "countries"
      }
    }
  ]
}

Далее используется обычный geopath.


Отрисовка границ

Частая задача — рисование только контуров.

"encode": {
  "update": {
    "fill": {
      "value": null
    },
    "stroke": {
      "value": "#000"
    }
  }
}

Отрисовка нескольких слоёв

Карта обычно состоит из нескольких наборов данных:

  • страны;
  • реки;
  • города;
  • маршруты;
  • подписи.

Пример:

"marks": [
  {
    "type": "shape",
    "from": {"data": "countries"}
  },
  {
    "type": "shape",
    "from": {"data": "rivers"}
  }
]

Трансформация geopoint

Назначение

geopoint преобразует географические координаты:

longitude, latitude

в экранные координаты:

x, y

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

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

Базовый пример geopoint

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",

  "width": 800,
  "height": 500,

  "data": [
    {
      "name": "cities",
      "values": [
        {
          "city": "Москва",
          "lon": 37.6173,
          "lat": 55.7558
        },
        {
          "city": "Париж",
          "lon": 2.3522,
          "lat": 48.8566
        }
      ]
    }
  ],

  "projections": [
    {
      "name": "projection",
      "type": "mercator",
      "scale": 130,
      "translate": [400, 250]
    }
  ],

  "marks": [
    {
      "type": "symbol",

      "from": {
        "data": "cities"
      },

      "transform": [
        {
          "type": "geopoint",
          "projection": "projection",
          "fields": ["lon", "lat"]
        }
      ],

      "encode": {
        "update": {
          "x": {"field": "x"},
          "y": {"field": "y"},
          "size": {"value": 100},
          "fill": {"value": "red"}
        }
      }
    }
  ]
}

Как работает geopoint

Исходные координаты

37.6173, 55.7558

Проекция

mercator

Вычисление экранной позиции

x = 512
y = 220

Передача в symbol

"x": {"field": "x"},
"y": {"field": "y"}

Параметры geopoint

Параметр Назначение
projection Географическая проекция
fields Поля longitude и latitude
as Названия результирующих полей

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

По умолчанию:

x
y

Можно изменить:

{
  "type": "geopoint",
  "projection": "projection",
  "fields": ["lon", "lat"],
  "as": ["screenX", "screenY"]
}

geopath против geopoint

geopath geopoint
Геометрии Координаты
Polygon Point
Shape Symbol
SVG path x/y
Карты Маркеры

Трансформация geoshape

Назначение

geoshape — специализированный shorthand для отрисовки геометрии.

Фактически это более компактный способ использования geopath.


Отличие geoshape от geopath

geopath:

{
  "transform": [
    {
      "type": "geopath",
      "projection": "projection"
    }
  ]
}

geoshape:

{
  "type": "geoshape",
  "projection": "projection"
}

Пример geoshape

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "width": 800,
  "height": 500,

  "data": {
    "url": "world.geojson",
    "format": {
      "type": "geojson"
    }
  },

  "projection": {
    "type": "mercator"
  },

  "mark": {
    "type": "geoshape",
    "fill": "#bde0fe",
    "stroke": "#333"
  }
}

geoshape в Vega-Lite

В Vega-Lite geoshape используется значительно чаще, чем geopath.

Причины:

  • декларативность;
  • краткость;
  • автоматическое создание path;
  • интеграция с projection;
  • меньше служебного кода.

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

GeoJSON Feature:

{
  "type": "Feature",
  "geometry": {
    "type": "Polygon"
  },
  "properties": {
    "name": "Country"
  }
}

geoshape автоматически извлекает geometry.


Комбинирование geoshape и geopoint

Очень распространённый сценарий:

  • карта через geoshape;
  • города через geopoint.

Полный пример

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",

  "width": 900,
  "height": 500,

  "data": [
    {
      "name": "countries",
      "url": "world.geojson",
      "format": {
        "type": "geojson"
      }
    },
    {
      "name": "cities",
      "values": [
        {
          "name": "Москва",
          "lon": 37.6173,
          "lat": 55.7558
        },
        {
          "name": "Берлин",
          "lon": 13.4050,
          "lat": 52.5200
        }
      ]
    }
  ],

  "projections": [
    {
      "name": "projection",
      "type": "mercator",
      "scale": 140,
      "translate": [450, 250]
    }
  ],

  "marks": [
    {
      "type": "shape",

      "from": {
        "data": "countries"
      },

      "transform": [
        {
          "type": "geopath",
          "projection": "projection"
        }
      ],

      "encode": {
        "update": {
          "fill": {
            "value": "#dde5b6"
          },
          "stroke": {
            "value": "#606c38"
          }
        }
      }
    },

    {
      "type": "symbol",

      "from": {
        "data": "cities"
      },

      "transform": [
        {
          "type": "geopoint",
          "projection": "projection",
          "fields": ["lon", "lat"]
        }
      ],

      "encode": {
        "update": {
          "x": {"field": "x"},
          "y": {"field": "y"},
          "size": {"value": 80},
          "fill": {"value": "red"}
        }
      }
    }
  ]
}

Геометрические типы

geopath и geoshape поддерживают:

Тип Описание
Point Точка
MultiPoint Набор точек
LineString Линия
MultiLineString Несколько линий
Polygon Полигон
MultiPolygon Несколько полигонов
GeometryCollection Коллекция геометрий

Работа с LineString

Пример маршрута:

{
  "type": "LineString",
  "coordinates": [
    [37.6173, 55.7558],
    [2.3522, 48.8566]
  ]
}

Визуализация маршрутов

{
  "type": "shape",

  "transform": [
    {
      "type": "geopath",
      "projection": "projection"
    }
  ],

  "encode": {
    "update": {
      "stroke": {
        "value": "blue"
      },
      "strokeWidth": {
        "value": 2
      },
      "fill": {
        "value": null
      }
    }
  }
}

Центрирование карты

Проекция поддерживает:

Параметр Назначение
center Центр карты
translate Смещение
scale Масштаб
rotate Вращение

Пример

{
  "type": "mercator",
  "center": [30, 50],
  "scale": 500
}

Автоматический fit

Vega может автоматически масштабировать карту:

{
  "name": "projection",
  "type": "mercator",
  "fit": {
    "signal": "data('countries')"
  }
}

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

Масштабирование карты:

{
  "signals": [
    {
      "name": "zoom",
      "value": 150,
      "bind": {
        "input": "range",
        "min": 50,
        "max": 500
      }
    }
  ]
}

Динамический scale

{
  "name": "projection",
  "type": "mercator",
  "scale": {
    "signal": "zoom"
  }
}

Производительность

GeoJSON-файлы могут быть очень большими.

Основные методы оптимизации:

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

Проблемы проекций

Разные проекции:

  • искажают площадь;
  • искажают расстояния;
  • искажают углы;
  • искажают форму объектов.

Например:

Проекция Искажение
Mercator Сильное увеличение полюсов
EqualEarth Искажение формы
Orthographic Только полушарие

Частые ошибки

Отсутствует projection

Ошибка:

Cannot read property projection

Причина:

{
  "type": "geopath"
}

Без:

"projection": "projection"

Перепутаны latitude и longitude

Правильно:

[longitude, latitude]

Неправильно:

[latitude, longitude]

Неверный тип данных

Ошибка:

coordinates must be numbers

Причина:

"lat": "55.75"

Вместо:

"lat": 55.75

Использование geoshape в Vega-Lite

Пример choropleth-карты:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",

  "width": 800,
  "height": 500,

  "data": {
    "url": "world.geojson",
    "format": {
      "type": "geojson"
    }
  },

  "projection": {
    "type": "equalEarth"
  },

  "mark": "geoshape",

  "encoding": {
    "color": {
      "field": "population",
      "type": "quantitative"
    }
  }
}

geoshape и lookup

Часто карта объединяется с внешними данными.

Пример:

{
  "transform": [
    {
      "lookup": "id",
      "from": {
        "data": {
          "url": "stats.csv"
        },
        "key": "country_id",
        "fields": ["population"]
      }
    }
  ]
}

geopath внутри Vega pipeline

geopath — полноценная transform-операция.

Её можно комбинировать с:

  • filter;
  • formula;
  • lookup;
  • aggregate;
  • collect;
  • joinaggregate.

Фильтрация геометрии

{
  "type": "filter",
  "expr": "datum.properties.population > 10000000"
}

Генерация подписей

Подписи городов:

{
  "type": "text",

  "encode": {
    "update": {
      "text": {
        "field": "city"
      }
    }
  }
}

Совместно с geopoint:

"x": {"field": "x"},
"y": {"field": "y"}

Интерактивные карты

Поддерживаются:

  • hover;
  • zoom;
  • pan;
  • tooltip;
  • selection;
  • click events.

Tooltip для geoshape

"tooltip": {
  "signal": "datum.properties.name"
}

Географические слои

Типичная архитектура:

Слой Технология
Подложка geoshape
Границы geopath
Города geopoint
Подписи text
Маршруты LineString

Когда использовать geopath

Подходит для:

  • сложных карт;
  • SVG-path обработки;
  • низкоуровневого контроля;
  • Vega pipeline;
  • кастомных shape.

Когда использовать geopoint

Подходит для:

  • scatter-карт;
  • GPS;
  • координатных данных;
  • маркеров;
  • интерактивных точек.

Когда использовать geoshape

Подходит для:

  • Vega-Lite;
  • быстрых карт;
  • choropleth;
  • компактного кода;
  • декларативной визуализации.