Изохроны

Обзор

Изохрона — территория, достижимая из точки отправления по транспортной сети в пределах бюджета времени или расстояния. ObjectNat строит изохроны на графе iduedu.UrbanGraph, подготовленном IduEdu (пешеходный, автомобильный, граф общественного транспорта или интермодальный). objectnat.get_graph_isochrones() возвращает один полигон на точку отправления; objectnat.get_stepped_graph_isochrones() делит достижимую территорию на пояса шириной step.

Метод

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

  2. Поиск Дейкстры идёт от точек отправления по направлению рёбер с весами time_min (минуты, по умолчанию) или length_meter (метры) до weight_value_cutoff. Поиски от всех точек выполняются одним параллельным вызовом процедур Numba из IduEdu.

  3. Достижимые узлы превращаются в полигон в зависимости от geometry_type. Остаток бюджета в узле (предел минус стоимость пути до узла) переводится в расстояние, для time_min — по медианной скорости на рёбрах графа (length_meter / time_min):

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

    • "ways": достижимые рёбра с буфером road_buffer_size метров, ограниченные буферами на всё остаточное расстояние;

    • "separate": буферы радиусом buffer_factor × остаточное расстояние вокруг достижимых узлов, объединённые в один полигон.

  4. Если задан zone, результат обрезается по нему.

Почему радиус ограничен. Буфер на всё остаточное расстояние предполагает, что из узла можно идти по прямой в любом направлении на весь остаток бюджета — через кварталы, дворы и воду. У точки отправления это весь бюджет, поэтому 10-минутная пешая изохрона превращается в круг радиусом около 800 м независимо от планировки улиц. Ограничение повторяет подход планировщиков поездок, таких как OpenTripPlanner и Conveyal R5: поиск идёт по сети, и только последний отрезок от улицы до места, не длиннее off_network_distance, проходится вне сети. Тогда изохрона следует за действительно достижимыми улицами и сужается там, где они заканчиваются. off_network_distance=None даёт буферы без ограничения.

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

Ступенчатые изохроны относят каждый достижимый узел к интервалу [0, step), [step, 2·step), …, в который попадает его стоимость, вплоть до weight_value_cutoff (по умолчанию — стоимость самого дальнего достижимого узла), и строят по одному поясу на интервал: geometry_type=None использует ячейки Вороного вокруг узлов, "radius" и "ways" обрезают эти ячейки по буферам остаточного расстояния или по буферам улиц, а "separate" строит независимые буферы для каждого интервала. При нескольких точках отправления пояса описывают их совместную достижимость: каждый узел получает стоимость от ближайшей точки. Столбец dist содержит верхнюю границу интервала.

Результаты

GeoDataFrame в системе координат входных точек. У objectnat.get_graph_isochrones() одна строка на точку отправления со столбцом source_node и входными атрибутами; у objectnat.get_stepped_graph_isochrones() одна строка на пояс и столбец dist (минуты или метры).

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

Рассчитывает изохроны доступности от объектов-точек отправления по городскому графу.

Изохрона — территория, достижимая из точки отправления в пределах weight_value_cutoff. В отличие от зон покрытия, каждая точка получает собственную независимую изохрону, но все поиски кратчайших путей выполняются одним параллельным вызовом Numba. Функция:

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

  2. Параллельно выполняет по одному поиску Дейкстры на точку.

  3. Строит полигон достижимости для каждой точки с выбранным geometry_type.

  4. При необходимости обрезает каждую изохрону по zone.

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

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

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

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

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

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

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

    • "time_min": доступность по времени в минутах

    • "length_meter": доступность по расстоянию в метрах

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

    Способ построения каждой изохроны:

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

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

    • "separate": буферы радиусом buffer_factor × остаточное расстояние вокруг достижимых узлов, объединённые в один полигон

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

  • 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.

  • max_workers (int, optional) – Число параллельных потоков Numba. По умолчанию определяется средой Numba.

Результат:

Один полигон изохроны на точку отправления со столбцом source_node и geometry в системе координат gdf_origins (или графа). Индекс совпадает с gdf_origins / origin_nodes.

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

gpd.GeoDataFrame

Заметки

  • Для geometry_type="ways" бюджет поиска немного увеличивается, чтобы рёбра улиц не обрывались раньше границы.

  • Точки отправления без достижимых узлов исключаются из результата.

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

objectnat.get_stepped_graph_isochrones(urban_graph, *, gdf_origins=None, origin_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)[исходный код]

Рассчитывает ступенчатые изохроны доступности от объектов-точек отправления по городскому графу, разбивая каждую достижимую территорию на концентрические пояса шириной step.

В отличие от зон покрытия, поиск идёт от точек отправления наружу (по исходному направлению рёбер ориентированного графа). Функция:

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

  2. Выполняет многоисточниковый поиск Дейкстры от точек отправления.

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

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

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

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

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

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

  • 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_origins (или графа).

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

gpd.GeoDataFrame

Заметки

  • Несколько точек отправления обрабатываются вместе: пояса описывают совместную достижимость всех точек (каждый узел получает расстояние от ближайшей точки).

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

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

Рисунки

Изохроны с geometry_type ways и radius и изохроны трёх точек отправления

15-минутная изохрона на интермодальном графе Васильевского острова с geometry_type="ways" и "radius" и 8-минутные изохроны "radius" трёх точек отправления (по одному полигону на точку). Фон: пешеходные улицы графа и граница района.

Ступенчатые изохроны с geometry_type ways, radius и separate

Ступенчатые изохроны до 15 минут поясами по 3 минуты, geometry_type="ways", "radius" и "separate"; dist — верхняя граница пояса. Фон: пешеходные улицы графа и граница района.

Ограничения

  • Время в пути берётся из графа (time_min); пробки, расписания (кроме времени ожидания, которое моделирует IduEdu) и штрафы за повороты не учитываются.

  • Полигон вне сети — интерполяция. "radius" предполагает движение по прямой не дальше off_network_distance от улиц; "separate" — на весь остаток бюджета и поэтому завышает достижимость через кварталы без проходов.

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

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

Изохроны