Анализ видимости

Обзор

Анализ видимости определяет, какие части городского пространства видит наблюдатель, а при агрегировании по множеству наблюдателей — как часто видно каждое место. В ObjectNat есть две модели:

  • Видимость 2D (objectnat.get_visibility(), objectnat.get_isovist_grid(), objectnat.get_visibility_catchment()): каждое препятствие — стена бесконечной высоты. Результат для одного наблюдателя — его полигон видимости (изовиста), векторный полигон, граница которого вычисляется точно.

  • Видимость 2.5D (objectnat.get_viewshed(), objectnat.get_viewshed_catchment()): у зданий есть высота, а рельеф может поднимать землю. Результат для одного наблюдателя — его область видимости: ячейки сетки, до которых луч зрения от глаз свободен, объединённые в один (Multi)Polygon на наблюдателя. Её контур идёт по ячейкам, поэтому точность равна cell_size.

Функции охвата подсчитывают для каждой ячейки сетки наблюдателей, которые её видят; результат рисуется растром. objectnat.get_observer_points() размещает наблюдателей вдоль улиц графа IduEdu. Все расчёты выполняются в параллельных потоках в расширении ObjectNat на Rust.

Результаты на сетке отвечают на два разных вопроса, и их значения имеют разные единицы. Поле изовист (objectnat.get_isovist_grid()) описывает, что видит наблюдатель, стоящий в каждой ячейке, например видимую долю круга обзора: оно смотрит из места наружу. Охват подсчитывает наблюдателей, которые видят каждую ячейку: он смотрит на место со стороны улиц. Его единица — число наблюдателей (или сумма их весов) и в 2D, и в 2.5D. У середины большой площади видимая доля высокая, а охват низкий, если к ней ведёт мало улиц.

Полигоны видимости 2D

Метод

objectnat.get_visibility() возвращает для каждого наблюдателя часть круга обзора (радиусом view_distance или из столбца visibility_distance для каждого наблюдателя, в метрах), не скрытую за стенами препятствий. Препятствия могут быть полигонами (с дырами) или линиями. Наблюдатели и препятствия перепроецируются в оценённую зону UTM. Стены препятствий обрезаются по кругу, каждый конец стены и каждое пересечение стен задают критическое направление, и один луч на каждый угловой интервал находит ближайшую стену. Поэтому граница точная: лучи с фиксированным шагом по углу не используются. Наблюдатели внутри препятствия получают пустой полигон.

Метрики изовист

Изовиста — это полигон видимости одного наблюдателя. При isovist_metrics=True функция objectnat.get_visibility() описывает каждую изовисту показателями ниже (Benedikt 1979; Turner et al. 2001; Batty 2001): сколько видит наблюдатель, какую форму имеет видимая область и сколько пространства скрыто за углами. Длины — в метрах, площади — в квадратных метрах; наблюдатели внутри препятствия получают NaN.

Граница изовисты состоит из рёбер трёх видов: видимых частей стен, дуг границы дальности обзора (окружности радиусом view_distance) и рёбер окклюзии. Ребро окклюзии лежит на луче зрения, проходящем мимо угла здания. За углом луч продолжается в пространство, которого наблюдатель не видит, поэтому ребро отделяет видимую область от скрытой.

Примеры в таблице даны для дальности обзора R = 200 м и трёх простых мест: чистого поля без препятствий, середины прямой улицы шириной 20 м между сплошными стенами и закрытого квадратного двора 40 × 40 м.

Столбцы

Что измеряют

Примеры

area, visible_share

Сколько видит наблюдатель: площадь изовисты и её отношение к площади круга обзора π R².

Поле: visible_share = 1. Улица: полоса примерно 20 × 400 м, поэтому area ≈ 8000 м², а visible_share ≈ 0,06.

perimeter, compactness

Длина границы изовисты и 4πA/P² — сравнение формы с кругом: 1 для круга, около 0 для длинной узкой или звездообразной формы.

Поле: 1. Двор изнутри: π/4 ≈ 0,79. Улица: ≈ 0,14.

n_occlusions, occlusivity

Число рёбер окклюзии и их суммарная длина: мимо скольких углов смотрит наблюдатель и как далеко за ними тянется скрытое пространство.

Поле, улица и двор: 0, ничего не скрыто. Одно здание в поле: два ребра, стороны его «тени». Пересечения узких проходов между зданиями: большие значения.

min_radial, max_radial

Расстояние от наблюдателя до ближайшей точки границы, обычно до ближайшей стены, и длина самого дальнего луча зрения.

Улица: 10 м (стены) и 200 м (вдоль улицы).

mean_radial, std_radial, skew_radial

Расстояние от наблюдателя до конца взгляда (стены, ребра окклюзии или границы дальности обзора) по всем направлениям: его среднее, стандартное отклонение и асимметрия. Они интегрируются точно по каждому ребру границы.

Поле: среднее 200 м, стандартное отклонение 0. Улица: среднее ≈ 30 м, стандартное отклонение ≈ 41 м; асимметрия положительна, потому что немногие длинные взгляды вдоль улицы выделяются среди множества коротких взглядов в стены.

drift

Расстояние от наблюдателя до центроида изовисты: 0, когда видимая область уравновешена вокруг наблюдателя, и большое значение, когда она в основном лежит с одной стороны.

Центр двора: 0. У середины одной из стен двора: 20 м.

open_share

Доля длины границы, лежащая на границе дальности обзора, то есть не на стенах и не на рёбрах окклюзии.

Поле: 1. Двор: 0. Улица: два торца полосы, 40 м из 840 м границы, ≈ 0,05.

Метрики почти не увеличивают время расчёта видимости (около 0,8 с на 5000 полигонов видимости с 450 000 вершин в сумме).

objectnat.get_visibility(point_from, obstacles, view_distance=None, *, max_workers=None, isovist_metrics=False)[исходный код]

Вычисляет полигоны видимости для одной или многих точек наблюдения.

Каждый наблюдатель получает точную видимую область в пределах дальности обзора: круг обзора за вычетом всего, что скрыто за стенами препятствий. Для расчёта точки и препятствия перепроецируются в локально оценённую проецированную систему координат (обычно UTM), а наблюдатели обрабатываются параллельно в расширении ObjectNat на Rust.

Параметры:
  • point_from (geopandas.GeoDataFrame) – GeoDataFrame с точечными геометриями мест наблюдения. Должен иметь корректную систему координат. Все дополнительные атрибуты сохраняются в результате.

  • obstacles (geopandas.GeoDataFrame) – GeoDataFrame с геометриями препятствий (Polygon, MultiPolygon, LineString, MultiLineString) в любой системе координат. Если он пуст или None, препятствий нет и видимость ограничена только дальностью обзора.

  • view_distance (float | None, optional) – Общая дальность обзора для всех точек (в метрах). Используется, если в point_from нет столбца "visibility_distance". Если None и столбца тоже нет, возникает ValueError.

  • max_workers (int | None, optional) – Максимальное число потоков (None — все ядра).

  • isovist_metrics (bool, optional) – Если True, добавляет к результату столбцы метрик изовист, измеренные в метрах в локальной системе координат: area, perimeter, compactness (4πA/P², 1 для полного круга), occlusivity (суммарная длина рёбер окклюзии), n_occlusions, min_radial, max_radial, mean_radial, std_radial, skew_radial (моменты расстояния до границы по всем направлениям, интегрированные точно), drift (расстояние от наблюдателя до центроида), visible_share (площадь / площадь круга обзора) и open_share (доля границы на границе дальности обзора). Наблюдатели внутри препятствия получают NaN.

Результат:

GeoDataFrame с тем же индексом и атрибутами, что point_from, но со столбцом геометрии, заменённым полигонами видимости. Результат возвращается в исходной системе координат point_from. Наблюдатели внутри препятствия получают пустой полигон.

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

gpd.GeoDataFrame

Исключение:
  • TypeError – Если point_from не GeoDataFrame.

  • ValueError – Если point_from пуст или не имеет системы координат, или если не задан ни view_distance, ни столбец "visibility_distance".

Заметки

Если в point_from есть столбец "visibility_distance", его значения используются как дальность обзора каждой точки, а аргумент view_distance игнорируется.

Полигоны видимости одного наблюдателя и трёх наблюдателей с разными радиусами

Слева: полигон видимости одного наблюдателя в пределах 800 м среди зданий из примера. Справа: три наблюдателя с visibility_distance 300, 500 и 800 м.

Поле изовист

objectnat.get_isovist_grid() строит карту метрик по территории. Функция ставит наблюдателя в центр каждой ячейки размером cell_size вне препятствий, вычисляет точную изовисту каждого наблюдателя и её метрики и возвращает наблюдателей как точки со столбцами метрик. Препятствия за пределами территории, но в пределах view_distance от неё, тоже закрывают обзор. Каждое значение точно для своего наблюдателя; сетка задаёт только то, где стоят наблюдатели. objectnat.rasterize() превращает любую метрику в растр (см. Растры), который показывает для каждого места, что увидел бы стоящий там наблюдатель. Время пропорционально числу наблюдателей: поле ниже, 7889 наблюдателей с дальностью обзора 200 м, рассчитывается за 0,7 с.

У поля нет краевого эффекта: значение описывает только своего наблюдателя, а здания за пределами территории учитываются. Для наблюдателей, расставленных иначе, например вдоль улиц, те же метрики вычисляет objectnat.get_visibility():

from objectnat import get_observer_points, get_visibility

observers = get_observer_points(walk_graph, spacing=15)            # a point every 15 m along the streets
metrics = get_visibility(observers, buildings, view_distance=200, isovist_metrics=True)
metrics.set_geometry(observers.geometry).plot(column="visible_share", markersize=4)
objectnat.get_isovist_grid(obstacles, area, *, view_distance=200.0, cell_size=5.0, max_workers=None)[исходный код]

Метрики изовист на регулярной сетке наблюдателей, покрывающей открытую территорию (поле изовист).

Наблюдатель ставится в центр каждой ячейки размером cell_size в area вне препятствий, и его точный полигон видимости в пределах view_distance измеряется так же, как в get_visibility(..., isovist_metrics=True). Препятствия за пределами территории, но в пределах view_distance от неё, тоже закрывают обзор. rasterize() превращает любую метрику в Raster, который показывает, как меняются открытость, компактность или окклюзия по территории.

Параметры:
  • obstacles (gpd.GeoDataFrame | None) – Геометрии препятствий (Polygon, MultiPolygon, LineString, MultiLineString) в любой системе координат; None или пустой набор для открытой местности.

  • area (gpd.GeoDataFrame | gpd.GeoSeries | shapely.Geometry) – Покрываемая территория. Геометрия shapely считается заданной в системе координат obstacles.

  • view_distance (float, optional) – Дальность обзора каждого наблюдателя в метрах. По умолчанию 200.

  • cell_size (float, optional) – Шаг наблюдателей в метрах. Время растёт как (area / cell_size²) * view_distance. По умолчанию 5.

  • max_workers (int | None, optional) – Число потоков (None — все ядра).

Результат:

Одна точка наблюдателя на открытую ячейку в системе координат area (obstacles для геометрии shapely) со столбцами метрик изовист из get_visibility(): area, perimeter, compactness, occlusivity, n_occlusions, min_radial, max_radial, mean_radial, std_radial, skew_radial, drift, visible_share и open_share. attrs записывают сетку для rasterize().

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

gpd.GeoDataFrame

Исключение:

ValueError – Если у area нет системы координат или она пуста, либо view_distance или cell_size не положительны.

Карты четырёх метрик изовист

get_isovist_grid(buildings, area, view_distance=200, cell_size=5) на территории 500 × 500 м (обведена) и objectnat.rasterize() четырёх метрик: видимая доля круга радиусом 200 м, компактность 4πA/P², суммарная длина рёбер окклюзии и drift. Цветовые шкалы охватывают 2–98-й процентили. На открытом пространстве на юге видна бо́льшая часть круга; компактность высока там и внутри закрытых дворов; рёбра окклюзии длиннее всего на пересечениях проходов между зданиями; drift велик у стен, обращённых к открытому пространству.

Области видимости 2.5D

Метод

objectnat.get_viewshed() учитывает высоты зданий и рельеф. Глаза наблюдателя находятся на observer_height (по умолчанию 1,6 м) над рельефом, а у наблюдателя внутри контура здания — над крышей. Территория в пределах дальности обзора делится на квадратные ячейки размером cell_size метров. Ячейка видна, если прямая от глаз до центра ячейки на высоте target_height над землёй (0 м для поверхности земли, около 1,6 м для лиц людей) проходит выше каждой пересекаемой стены и выше рельефа. Видимые ячейки объединяются в один (Multi)Polygon на наблюдателя. При include_roofs=True целями служат и ячейки на плоских крышах, на высоте крыши. Высоты зданий и рельеф задаются так же, как для objectnat.get_insolation() (столбец высоты или этажности; рельеф как GeoDataFrame, GeoTIFF или массив), а проверка луча зрения использует ту же реализацию на Rust, что и инсоляция.

Результат сохраняет индекс и атрибуты наблюдателей и добавляет visible_area (м²) и visible_share — долю видимых целевых ячеек в пределах дальности обзора, аналог одноимённой метрики изовисты в 2.5D. Столбцы visibility_distance и observer_height заменяют аргументы для отдельных наблюдателей. Время расчёта растёт как (view_distance / cell_size) ** 2 на наблюдателя.

Для наблюдателя на ровной земле, глаза которого ниже всех окружающих зданий, область видимости совпадает с полигоном видимости 2D с точностью до размера ячейки. Они различаются там, где здания ниже луча зрения: с крыши, с холма или когда цель выше земли (target_height).

objectnat.get_viewshed(point_from, buildings, view_distance=None, *, height_column='height', storeys_column=None, storey_height=3.0, default_height=None, terrain=None, terrain_height_column='height', terrain_cell=5.0, observer_height=1.6, target_height=0.0, cell_size=2.0, include_roofs=False, max_workers=None)[исходный код]

Вычисляет видимость 2.5D: землю (и, при необходимости, крыши), которую каждый наблюдатель видит с высоты своих глаз среди зданий известной высоты и рельефа.

В отличие от get_visibility(), где каждое препятствие бесконечно высокое, здесь низкое здание или холм скрывает только то, что ниже луча зрения: наблюдатель видит через гараж улицу за ним, с холма — поверх крыш, с башни — далеко через весь район. Территория в пределах view_distance делится на ячейки размером cell_size, и ячейка видна, если прямая от глаз до центра ячейки (на высоте target_height над землёй) проходит выше каждой пересекаемой стены здания и выше рельефа. Видимые ячейки объединяются в один полигон на наблюдателя. Глаза находятся на observer_height над рельефом; наблюдатели внутри контура здания ставятся на его крышу.

Параметры:
  • point_from (geopandas.GeoDataFrame) – Точки наблюдения в любой системе координат. Необязательные столбцы visibility_distance и observer_height заменяют view_distance и observer_height для отдельных точек; остальные атрибуты сохраняются.

  • buildings (gpd.GeoDataFrame | None) – Контуры зданий с высотами (см. height_column, storeys_column); None, если учитывается только рельеф.

  • view_distance (float | None, optional) – Дальность обзора в метрах, если в point_from нет visibility_distance.

  • height_column (str | None) – Высоты зданий, как в get_insolation().

  • storeys_column (str | None) – Высоты зданий, как в get_insolation().

  • storey_height (float) – Высоты зданий, как в get_insolation().

  • default_height (float | None) – Высоты зданий, как в get_insolation().

  • terrain (GeoDataFrame | str | PathLike | tuple | None) – Высоты земли, как в get_insolation(); без рельефа земля ровная.

  • terrain_height_column (str) – Высоты земли, как в get_insolation(); без рельефа земля ровная.

  • terrain_cell (float) – Высоты земли, как в get_insolation(); без рельефа земля ровная.

  • observer_height (float, optional) – Высота глаз над рельефом (или над крышей) в метрах. По умолчанию 1.6.

  • target_height (float, optional) – Высота над землёй того, на что смотрят, в метрах: 0 для самой земли, 1.6, чтобы видеть лица людей, больше — для верхних частей объектов. По умолчанию 0.

  • cell_size (float, optional) – Размер ячейки в метрах; время растёт как (view_distance / cell_size) ** 2. По умолчанию 2.

  • include_roofs (bool, optional) – Возвращать также видимые части крыш (плоские крыши на высоте здания). По умолчанию False: контуры зданий исключаются.

  • max_workers (int | None, optional) – Число потоков (None — все ядра).

Результат:

Тот же индекс и атрибуты, что у point_from, с геометрией, заменённой видимой областью (ячейки, объединённые в полигоны, или пустой полигон, если ничего не видно), в системе координат point_from, а также visible_area (м²) и visible_share (доля видимых целевых ячеек в пределах дальности обзора).

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

gpd.GeoDataFrame

Исключение:

ValueError – Если point_from пуст или не имеет системы координат либо не задана дальность обзора.

Полигон видимости 2D, область видимости с уровня улицы и с крыши

Один наблюдатель на улице: полигон видимости 2D (слева) и область видимости 2.5D с глазами на высоте 1,6 м (в центре), обе по 2,8 га в пределах 300 м (пунктирная окружность). Справа: наблюдатель на краю крыши 17-этажного здания, include_roofs=True; область видимости охватывает 9,6 га земли и крыш. Оттенки серого показывают высоту зданий; cell_size=2.

Охват видимости

Метод

objectnat.get_visibility_catchment() отвечает на вопрос из скольких мест видно это место? Функция берёт набор наблюдателей, например пешеходов через каждые 15 м вдоль улиц, и для каждого небольшого участка территории считает, сколько из них его видят:

  1. Наблюдатели. objectnat.get_observer_points() расставляет их вдоль улиц графа: делит каждое ребро улицы (на пешеходных и интермодальных графах — каждое пешеходное ребро) на отрезки длиной около spacing метров и ставит точку в середину каждого отрезка. Подойдут любые точки.

  2. Сетка. Территория в пределах view_distance от наблюдателей делится на квадратные ячейки размером cell_size метров.

  3. Подсчёт. Для каждого наблюдателя вычисляется полигон видимости, как в objectnat.get_visibility(), и каждая ячейка, центр которой лежит внутри него, получает ещё одного наблюдателя (или вес наблюдателя из weight_column, например пешеходный поток). Поэтому значение ячейки — это число наблюдателей, которые её видят. Полигоны только подсчитываются и не возвращаются, что экономит память.

  4. Результат. Ячейки, которые видит хотя бы один наблюдатель, возвращаются точками в центрах ячеек с их count (и weight); ячейки внутри зданий и ячейки, которые никто не видит, исключаются. objectnat.rasterize() возвращает их на сетку — получается растр, который показывает значения непрерывной цветовой шкалой.

Например, при наблюдателях через 15 м и дальности обзора 250 м площадь, на которую выходят несколько улиц, видят сто наблюдателей и больше, а закрытый двор — лишь несколько наблюдателей внутри него.

Расставляйте наблюдателей шире анализируемой территории. Ячейку у края территории видят и наблюдатели за её пределами, на расстоянии до view_distance. Если наблюдатели заканчиваются на границе территории, счёт у границы получается заниженным. Расставьте наблюдателей по территории, расширенной на view_distance, и обрежьте результат по самой территории.

Время и память растут с числом ячеек. Значения выражены в числе наблюдателей, поэтому две территории или два сценария с одинаковым шагом наблюдателей можно рисовать в одной цветовой шкале. Видимость симметрична, поэтому значение ячейки — это и число наблюдателей, видимых из этой ячейки.

objectnat.get_viewshed_catchment() — аналог в 2.5D: ячейка засчитывает наблюдателя, если луч зрения от его глаз до цели в ячейке свободен, как в objectnat.get_viewshed(). Наблюдатели внутри контуров зданий исключаются. Контуры зданий растеризуются один раз, а лучи зрения всех наблюдателей подсчитываются в расширении на Rust. При include_roofs=True подсчитываются и ячейки крыш; с уровня улицы крыши видны только там, где рельеф или observer_height поднимает глаза выше них.

objectnat.get_visibility_catchment(observers, obstacles, *, view_distance=None, cell_size=5.0, weight_column=None, max_workers=None)[исходный код]

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

Территория в пределах view_distance от наблюдателей делится на квадратные ячейки. Ячейка засчитывает наблюдателя, если её центр лежит внутри его точного полигона видимости (см. get_visibility()); с weight_column она суммирует веса наблюдателей. Если наблюдатели густо расставлены вдоль улиц (см. get_observer_points()), значения показывают, откуда объекты видны чаще всего: визуальный охват фасадов, площадей и ориентиров. rasterize() превращает результат в Raster.

Параметры:
  • observers (geopandas.GeoDataFrame) – Точки наблюдения с системой координат.

  • obstacles (gpd.GeoDataFrame | None) – Геометрии препятствий (Polygon, MultiPolygon, LineString, MultiLineString) в любой системе координат. None или пустой набор — препятствий нет.

  • view_distance (float | None, optional) – Дальность обзора каждого наблюдателя в метрах. Используется, если у observers нет столбца "visibility_distance"; нужно одно из двух.

  • cell_size (float, optional) – Сторона ячейки в метрах. Уменьшение вдвое даёт вчетверо больше ячеек, и с ними растут память и время.

  • weight_column (str | None, optional) – Столбец неотрицательных весов наблюдателей (например, пешеходного потока). Тогда ячейки суммируют веса видящих их наблюдателей вместо подсчёта. Наблюдатели с нулевым или отсутствующим весом игнорируются.

  • max_workers (int | None, optional) – Число потоков (None — все ядра).

Результат:

Ячейки, которые видит хотя бы один наблюдатель, в виде точек в центрах ячеек в системе координат observers со столбцом count (число наблюдателей, которые видят ячейку) и, при weight_column, weight (сумма их весов). Ячейки, которые никто не видит, в том числе внутри препятствий, исключаются. attrs записывают сетку, поэтому rasterize() точно её восстанавливает.

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

gpd.GeoDataFrame

Исключение:
  • TypeError – Если observers не GeoDataFrame.

  • ValueError – Если observers пуст или не имеет системы координат, если не задана дальность обзора, если cell_size некорректен, если weight_column отсутствует или содержит отрицательные значения либо если сетка превысила бы 200 миллионов ячеек.

Заметки

Видимость симметрична, поэтому значение ячейки — это и число наблюдателей, видимых из неё.

objectnat.get_viewshed_catchment(observers, buildings, *, view_distance=None, height_column='height', storeys_column=None, storey_height=3.0, default_height=None, terrain=None, terrain_height_column='height', terrain_cell=5.0, observer_height=1.6, target_height=0.0, cell_size=5.0, include_roofs=False, weight_column=None, max_workers=None)[исходный код]

Подсчитывает для каждого места вокруг наблюдателей, сколько из них его видят, среди зданий известной высоты и рельефа (охват видимости 2.5D).

Аналог get_visibility_catchment() в 2.5D: каждая ячейка вокруг наблюдателей получает число наблюдателей (или сумму их весов), луч зрения которых до центра ячейки на высоте target_height свободен, как в get_viewshed(). Наблюдатели стоят на земле, глаза на observer_height над рельефом; наблюдатели внутри контура здания исключаются. С include_roofs подсчитываются и ячейки крыш, что показывает крыши и верхние части зданий, видимые с улиц.

Параметры:
  • observers (geopandas.GeoDataFrame) – Точки наблюдения с системой координат, например из get_observer_points(). Необязательные столбцы visibility_distance и observer_height заменяют view_distance и observer_height для отдельных точек.

  • buildings (gpd.GeoDataFrame | None) – Контуры зданий с высотами; None, если учитывается только рельеф.

  • view_distance (float | None, optional) – Дальность обзора в метрах, если у observers нет visibility_distance.

  • height_column (str | None) – Высоты зданий, как в get_insolation().

  • storeys_column (str | None) – Высоты зданий, как в get_insolation().

  • storey_height (float) – Высоты зданий, как в get_insolation().

  • default_height (float | None) – Высоты зданий, как в get_insolation().

  • terrain (GeoDataFrame | str | PathLike | tuple | None) – Высоты земли, как в get_insolation().

  • terrain_height_column (str) – Высоты земли, как в get_insolation().

  • terrain_cell (float) – Высоты земли, как в get_insolation().

  • observer_height (float, optional) – Высота глаз над рельефом в метрах. По умолчанию 1.6.

  • target_height (float, optional) – Высота над землёй того, на что смотрят, в метрах. По умолчанию 0.

  • cell_size (float, optional) – Сторона ячейки в метрах. По умолчанию 5.

  • include_roofs (bool, optional) – Подсчитывать и ячейки крыш. По умолчанию False.

  • weight_column (str | None, optional) – Веса наблюдателей, как в get_visibility_catchment().

  • max_workers (int | None, optional) – Число потоков (None — все ядра).

Результат:

Ячейки, которые видит хотя бы один наблюдатель, в виде точек в центрах ячеек в системе координат observers с count (и weight), как в get_visibility_catchment(); rasterize() превращает их в Raster.

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

gpd.GeoDataFrame

Исключение:

ValueError – При пустом наборе наблюдателей, отсутствии дальности обзора, некорректных весах либо сетке больше 30 миллионов ячеек.

objectnat.get_observer_points(urban_graph, *, spacing=15.0)[исходный код]

Равномерно размещает точки наблюдения вдоль улиц графа.

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

Параметры:
  • urban_graph (UrbanGraph) – Граф улиц из IduEdu.

  • spacing (float, optional) – Желаемое расстояние между соседними точками в метрах.

Результат:

Точки в системе координат urban_graph, готовые для get_visibility_catchment().

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

gpd.GeoDataFrame

Исключение:

ValueError – Если spacing не положителен или у графа нет геометрии рёбер.

Охват видимости 2D и охват областей видимости 2.5D

Число наблюдателей, которые видят каждую ячейку: 1805 наблюдателей на открытой территории не дальше 12 м от зданий, расставленных по показанной территории, расширенной на дальность обзора, view_distance=250, cell_size=4; значения растеризованы функцией objectnat.rasterize() в одной цветовой шкале. Слева: 2D. Справа: 2.5D с target_height=10 — число наблюдателей, которые видят точку на высоте 10 м над землёй. Такую точку видно поверх зданий ниже луча зрения, поэтому её видит больше наблюдателей.

Ограничения

  • Видимость 2D не учитывает высоты: низкие стены, заборы и гаражи закрывают обзор так же, как высокие здания.

  • Области видимости 2.5D используют плоские крыши и вертикальные стены; деревья, уличная мебель и скатные крыши не моделируются. Результаты дискретны с шагом cell_size.

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

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

Видимость 2D: полигоны видимости, метрики изовист и охват (видимость 2D, метрики изовист, охват) и Видимость 2.5D: области видимости и их охват (области видимости 2.5D и их охват).