Зоны покрытия

Обзор

Зона покрытия — территория, которую обслуживает один сервис (пункт назначения) в пределах бюджета времени или расстояния; каждое место относится к сервису, ближайшему по сети. Зона покрытия отличается от изохроны в двух отношениях: поиск по сети идёт к сервисам (по обращённому графу), и зоны разных сервисов не перекрываются.

Метод

  1. Каждый сервис привязывается к ближайшему узлу графа, либо идентификаторы узлов берутся из graph_node_column или destination_nodes.

  2. Многоисточниковый поиск Дейкстры выполняется по обращённому графу сразу от всех сервисов, поэтому каждый узел помечается сервисом, до которого стоимость пути минимальна (time_min в минутах или length_meter в метрах), в пределах weight_value_cutoff.

  3. Вокруг узлов графа строятся ячейки Вороного, и ячейки узлов, помеченных одним сервисом, объединяются в его зону.

  4. Зоны обрезаются по zone (например, по границе города), а без него — по вогнутой оболочке достижимых узлов. geometry_type="radius" дополнительно обрезает их по буферам вокруг достижимых узлов радиусом в остаточное расстояние, но не больше off_network_distance (по умолчанию 150 м, как для изохрон), а geometry_type="ways" — по буферам улиц. Для time_min остаток времени переводится в расстояние по медианной скорости на рёбрах графа.

На пешеходных и интермодальных графах форму "ways" задают только пешеходные рёбра (type == "walk"), а геометрию любого типа — только их концевые узлы, как и для изохрон.

Ступенчатое покрытие помечает каждый узел стоимостью пути до ближайшего сервиса и строит по одному поясу на интервал стоимости шириной step: ячейки Вороного (geometry_type=None), ячейки, обрезанные по буферам остаточного расстояния или по улицам ("radius", "ways"), или независимые буферы ("separate").

objectnat.get_radius_coverage() перепроецирует сервисы в локальную зону UTM, строит их полигоны Вороного, обрезает их по объединению буферов радиусом radius метров вокруг сервисов и сглаживает каждый полигон внутренним буфером и следующим за ним чуть меньшим внешним, оба пропорциональны кубическому корню из площади полигона. Сглаживание скругляет углы, поэтому зоны могут быть немного меньше обрезанных ячеек Вороного.

Результаты

objectnat.get_graph_coverage() и objectnat.get_radius_coverage() возвращают по одному полигону на сервис с индексом входных сервисов (атрибуты сервисов присоединяются по индексу). objectnat.get_stepped_graph_coverage() возвращает полигоны со столбцом dist (верхняя граница интервала в минутах или метрах). Все результаты — в системе координат входных сервисов.

objectnat.get_graph_coverage(urban_graph, *, gdf_destinations=None, destination_nodes=None, graph_node_column='graph_node_id', weight_type='time_min', geometry_type=None, weight_value_cutoff=None, zone=None, buffer_factor=0.7, road_buffer_size=5.0, off_network_distance=150.0)[исходный код]

Рассчитывает зоны покрытия пунктов назначения (сервисов) на городском графе по достижимости Дейкстры и разбиению Вороного.

Зона покрытия отвечает на вопрос «какую территорию обслуживает каждый пункт назначения». Функция:

  1. Привязывает каждый пункт назначения к ближайшему узлу графа (или использует переданные destination_nodes).

  2. Выполняет многоисточниковый поиск Дейкстры по обращённому графу, так что каждый достижимый узел помечается ближайшим пунктом назначения в пределах weight_value_cutoff.

  3. Строит полигоны Вороного вокруг узлов графа.

  4. Объединяет достижимые ячейки Вороного каждого пункта назначения в одну зону.

  5. Обрезает результат по zone, по геометрии остаточного радиуса или улиц (geometry_type) или по вогнутой оболочке достижимых узлов.

Параметры:
  • urban_graph (UrbanGraph) – Городской граф с таблицами узлов (nodes_gdf) и рёбер (edges_gdf).

  • gdf_destinations (geopandas.GeoDataFrame, optional) – Пункты назначения, до которых измеряется покрытие. Если в таблице уже есть graph_node_column, используются эти идентификаторы узлов; иначе каждая геометрия привязывается к ближайшему узлу графа. Передайте либо этот параметр, либо destination_nodes.

  • destination_nodes (Iterable, optional) – Идентификаторы узлов пунктов назначения, используются вместо gdf_destinations.

  • graph_node_column (str) – Имя столбца с идентификаторами узлов графа в gdf_destinations.

  • weight_type (Literal['time_min', 'length_meter']) –

    Тип веса рёбер для расчёта путей:

    • "time_min": время проезда по ребру в минутах

    • "length_meter": длина ребра в метрах

  • geometry_type (Optional[Literal['radius', 'ways']]) –

    Необязательное уточнение формы зон:

    • None: исходные ячейки Вороного, обрезанные по zone или по вогнутой оболочке

    • "radius": дополнительная обрезка по буферам вокруг достижимых узлов (остаток бюджета в виде расстояния, не больше off_network_distance)

    • "ways": дополнительная обрезка по буферам улиц внутри остаточных радиусов (на интермодальных и пешеходных графах только пешеходные рёбра)

    Если задан, требует weight_value_cutoff.

  • weight_value_cutoff (float, optional) – Максимальная стоимость пути, например время в пути или расстояние. Единицы зависят от weight_type.

  • zone (gpd.GeoDataFrame | gpd.GeoSeries, optional) – Полигон границы, по которому обрезаются зоны. Если None и geometry_type не задан, используется вогнутая оболочка достижимых узлов.

  • buffer_factor (float) – Не используется зонами покрытия; принимается для единообразия с get_stepped_graph_coverage() (по умолчанию 0.7).

  • road_buffer_size (float) – Буфер рёбер графа для geometry_type="ways", в метрах (по умолчанию 5.0).

  • off_network_distance (float | None, optional) – Для geometry_type="radius": насколько далеко от сети, в метрах, может лежать место, чтобы считаться достигнутым. Каждый достижимый узел получает буфер радиусом в остаток бюджета, переведённый в расстояние, но не больше этого значения, поэтому территория повторяет сеть, а не разрастается в круг по прямой вокруг начальной точки. None строит буферы на весь остаток бюджета. По умолчанию 150.

Результат:

Один полигон покрытия на пункт назначения в системе координат gdf_destinations (или графа, если переданы идентификаторы узлов). Индекс совпадает с gdf_destinations / destination_nodes.

Тип результата:

gpd.GeoDataFrame

Заметки

  • Для ориентированного графа поиск идёт по обращённым рёбрам, поэтому зона описывает территорию, из которой можно добраться до её пункта назначения.

  • На пешеходных и интермодальных графах зоны строятся по узлам, достижимым пешком, поэтому узлы маршрутов на одной остановке не могут отдать одно место нескольким пунктам назначения.

  • Если ничего не достижимо, возвращается пустой GeoDataFrame.

objectnat.get_stepped_graph_coverage(urban_graph, *, gdf_destinations=None, destination_nodes=None, graph_node_column='graph_node_id', weight_type='time_min', geometry_type='radius', weight_value_cutoff=None, zone=None, step=None, buffer_factor=0.7, road_buffer_size=5.0, off_network_distance=150.0)[исходный код]

Рассчитывает ступенчатые зоны покрытия пунктов назначения (сервисов), сочетая достижимость по графу с поясной (ступенчатой) геометрией изохрон.

Как get_graph_coverage(), но вместо одной зоны на пункт назначения достижимая территория делится на концентрические пояса шириной step. Функция:

  1. Привязывает каждый пункт назначения к ближайшему узлу графа (или использует переданные destination_nodes).

  2. Выполняет многоисточниковый поиск Дейкстры по обращённому графу и помечает каждый достижимый узел стоимостью пути до ближайшего пункта назначения.

  3. Распределяет узлы по ступеням и строит геометрию поясов с выбранным geometry_type.

  4. При необходимости обрезает пояса по zone.

Параметры:
  • urban_graph (UrbanGraph) – Городской граф с таблицами узлов и рёбер.

  • gdf_destinations (geopandas.GeoDataFrame, optional) – Пункты назначения, до которых измеряется покрытие. Если в таблице есть graph_node_column, используются эти идентификаторы; иначе геометрии привязываются к ближайшим узлам. Передайте либо этот параметр, либо destination_nodes.

  • destination_nodes (Iterable, optional) – Идентификаторы узлов пунктов назначения, используются вместо gdf_destinations.

  • graph_node_column (str) – Имя столбца с идентификаторами узлов графа в gdf_destinations.

  • weight_type (Literal['time_min', 'length_meter']) –

    Тип веса рёбер для расчёта путей:

    • "time_min": время проезда по ребру в минутах

    • "length_meter": длина ребра в метрах

  • geometry_type (Optional[Literal['radius', 'ways', 'separate']]) –

    Способ построения геометрии каждой ступени:

    • None: ячейки Вороного вокруг узлов графа

    • "radius": ячейки Вороного, обрезанные по буферам радиуса (см. off_network_distance)

    • "ways": ячейки Вороного, обрезанные по буферам улиц (на интермодальных и пешеходных графах только пешеходные рёбра)

    • "separate": независимые круговые буферы для каждой ступени

  • weight_value_cutoff (float, optional) – Максимальная стоимость пути, ограничивающая покрытие. Если None, границу задаёт самый дальний достижимый узел.

  • zone (gpd.GeoDataFrame | gpd.GeoSeries, optional) – Полигон границы, по которому обрезаются ступенчатые зоны.

  • step (float, optional) – Ширина каждой ступени в единицах weight_type. По умолчанию 100 метров для length_meter и 1 минута для time_min.

  • buffer_factor (float) – Множитель буфера для geometry_type="separate" (по умолчанию 0.7).

  • road_buffer_size (float) – Буфер рёбер для geometry_type="ways", в метрах (по умолчанию 5.0).

  • off_network_distance (float | None, optional) – Для geometry_type="radius": насколько далеко от сети, в метрах, может лежать место, чтобы считаться достигнутым. Каждый достижимый узел получает буфер радиусом в остаток бюджета, переведённый в расстояние, но не больше этого значения, поэтому территория повторяет сеть, а не разрастается в круг по прямой вокруг начальной точки. None строит буферы на весь остаток бюджета. По умолчанию 150.

Результат:

Полигоны ступенчатого покрытия со столбцом dist (верхняя граница каждой ступени в единицах weight_type) и geometry в системе координат gdf_destinations (или графа).

Тип результата:

gpd.GeoDataFrame

Заметки

  • Для ориентированного графа поиск идёт по обращённым рёбрам; для неориентированного — по исходной симметричной смежности.

  • На пешеходных и интермодальных графах пояса строятся по узлам, достижимым пешком, поэтому узлы маршрутов транспорта на остановке, стоимость которых включает ожидание, не переносят её в более поздний пояс.

  • Если ничего не достижимо, возвращается пустой GeoDataFrame.

objectnat.get_radius_coverage(gdf_from, radius, resolution=32)[исходный код]

Рассчитывает зоны покрытия по радиусу с помощью полигонов Вороного.

Это покрытие без графа: зоны строятся только по точкам сервисов, фиксированному радиусу и разбиению Вороного, без сети.

Параметры:
  • gdf_from (geopandas.GeoDataFrame) – Точки сервисов, для которых рассчитываются зоны покрытия.

  • radius (float) – Максимальный радиус покрытия в метрах.

  • resolution (int) – Число сегментов на четверть окружности в буферах (по умолчанию 32).

Результат:

Сглаженные зоны покрытия, по одному полигону на точку, в системе координат gdf_from.

Тип результата:

gpd.GeoDataFrame

Заметки

  • Расчёт выполняется в локальной зоне UTM, поэтому radius задаётся в метрах.

  • Зоны сглаживаются небольшим внутренним и внешним буфером, который скругляет их углы.

Рисунки

Зоны покрытия по времени, по расстоянию и по радиусу

Зоны покрытия сервисов из примера: в пределах 10 минут на интермодальном графе с обрезкой по району, в пределах 600 м сетевого расстояния и без графа, objectnat.get_radius_coverage() с radius=800. Фон: пешеходные улицы графа и граница района.

Ступенчатые зоны покрытия для geometry_type None и separate

Ступенчатые зоны покрытия до 15 минут поясами по 2 минуты: geometry_type=None (ячейки Вороного узлов графа, обрезанные по району через zone) и "separate" (независимые буферы). "radius" и "ways" обрезают те же пояса Вороного по буферам радиуса или по буферам улиц. Фон: пешеходные улицы графа и граница района.

Ограничения

  • Каждое место относится к одному сервису — с наименьшей сетевой стоимостью; вместимость не учитывается. Для распределения спроса с учётом вместимости используйте Обеспеченность сервисами.

  • Границы зон между узлами сети задаются ячейками Вороного и буферами остаточного расстояния, а не планировкой улиц; их точность зависит от плотности узлов графа.

  • objectnat.get_radius_coverage() не учитывает сеть и барьеры, например реки или железные дороги.

Пример в ноутбуке

Зоны покрытия