Инсоляция¶
Обзор¶
Анализ инсоляции оценивает, сколько времени место получает прямой солнечный свет среди зданий известной высоты и, при необходимости, с учётом рельефа. objectnat.get_insolation() рассчитывает суточные часы солнца на регулярной сетке приёмников на земле; objectnat.get_facade_insolation() — для точек на фасадах на каждом этаже выбранных зданий. Обе функции принимают один день или период. Типичные задачи — проверка нормативов инсоляции для детских площадок и жилья, сравнение сценариев застройки и размещение растений, которым нужно прямое солнце.
Освещённая и затенённая земля 21 июня 2026 года в районе из примера (Васильевский остров, Санкт-Петербург, 59,96° с. ш.), кадр каждые 15 минут от восхода до заката. В заголовке — московское время (UTC+3), высота и азимут солнца.¶
Метод¶
Положение солнца. Для каждого моделируемого дня положение солнца вычисляется каждые time_step_min минут (в серединах интервалов местных солнечных суток) по алгоритму NOAA с учётом атмосферной рефракции; заявленная точность алгоритма около 0,01°. Дата и центр территории определяют путь солнца, поэтому учитываются широта и сезон. Положения ниже min_sun_elevation (градусы) считаются отсутствием солнца.
Сцена. Здания — выдавленные контуры с плоскими крышами. Высота здания берётся из height_column; если её нет — из storeys_column × storey_height; если нет обоих значений — из default_height. Здания без высоты пропускаются с предупреждением. Рельеф необязателен и задаётся как
GeoDataFrame полигонов с высотами в
terrain_height_column(например, зоны высот), растеризуемый с ячейкамиterrain_cell; перекрывающиеся полигоны дают наибольшее значение;путь к GeoTIFF (нужен
rasterio);кортеж
(heights, transform, crs)из двумерного массива, ориентированного на север аффинного преобразования в порядке rasterio и проецированной системы координат.
Здания стоят на рельефе по своему контуру, а приёмники размещаются на высоте receiver_height над рельефом. Расчёт идёт в локальной метрической системе координат (системе растра, если он задан, иначе в оценённой зоне UTM). Азимуты отсчитываются от истинного севера с поправкой на разницу между истинным севером и севером сетки (сближение меридианов).
Проверка тени. Для каждого приёмника и каждого положения солнца строится луч к солнцу. Приёмник освещён, если луч проходит выше каждой пересекаемой стены здания и выше рельефа. Луч прослеживается, только пока он ниже самой высокой крыши или точки рельефа в сцене, поэтому лучи к высокому солнцу заканчиваются рано и почти ничего не стоят. Проверка выполняется в расширении ObjectNat на Rust параллельно по приёмникам.
Суточная статистика. Для каждого приёмника и дня расширение на Rust возвращает число освещённых шагов времени и самый длинный непрерывный освещённый отрезок. Из них получаются три величины, все в часах:
sun_hours: среднесуточное прямое солнце за моделируемые дни;min_sun_hours: прямое солнце в худший моделируемый день;max_continuous_hours: наибольшая непрерывная продолжительность инсоляции в худший день (минимум по дням от наибольшего суточного отрезка). Нормативы инсоляции обычно задают минимум для этой величины; например, СанПиН 1.2.3685-21 (Россия) устанавливает минимальную непрерывную инсоляцию жилья и детских площадок.
Шаги времени дискретны, поэтому каждое значение кратно time_step_min.
Периоды. date=("2026-04-22", "2026-08-22") моделирует каждый day_step-й день периода и его последний день; сцена строится один раз.
Инсоляция на земле¶
objectnat.get_insolation() размещает приёмники с шагом grid_step метров внутри area (по умолчанию — охватывающего прямоугольника зданий) вне контуров зданий. Включайте в buildings здания вокруг территории: их тени падают на неё.
Результат — точки приёмников с sun_hours, min_sun_hours и max_continuous_hours; sun_hours равно 0 на земле, куда прямое солнце не попадает ни в один моделируемый день. attrs содержат моделируемые дни days, day_length_hours (среднее время, когда солнце выше min_sun_elevation) и сетку, поэтому objectnat.rasterize() превращает любой столбец в растр для карт, файлов GeoTIFF и веб-карт (см. Растры). Растр показывает часы непрерывной цветовой шкалой; пороги, например норматив, применяются к столбцам напрямую, например receivers["max_continuous_hours"] >= 2.5.
- objectnat.get_insolation(buildings, date, *, area=None, height_column='height', storeys_column=None, storey_height=3.0, default_height=None, terrain=None, terrain_height_column='height', terrain_cell=5.0, grid_step=2.0, time_step_min=10.0, day_step=7, min_sun_elevation=0.0, receiver_height=0.0, max_workers=None)[исходный код]¶
Часы прямого солнечного света на земле за день или за период среди зданий известной высоты и рельефа.
Солнце прослеживается в течение каждого моделируемого дня с шагом
time_step_min(положение солнца по NOAA для даты и места территории, с рефракцией), поэтому его путь меняется с широтой и сезоном. Для каждой точки регулярной сетки и каждого положения солнца вышеmin_sun_elevationстроится луч к солнцу; точка освещена, если луч проходит выше каждой пересекаемой стены здания и выше рельефа. Здания — выдавленные контуры с плоскими крышами, стоящие на рельефе. Результат показывает, сколько часов солнца получает каждое место и какие места всё время остаются в тени.- Параметры:
buildings (
geopandas.GeoDataFrame) – Контуры зданий (Polygon/MultiPolygon) в любой системе координат. Включайте и здания вокруг изучаемой территории: тени падают и от них.date (
datetime.date | str | tuple) – Один день ("2026-06-21") или период(start, end), оба дня включительно (("2026-04-22", "2026-08-22")). Каждый день рассчитывается от восхода до заката.area (
gpd.GeoDataFrame | gpd.GeoSeries | shapely geometry | None, optional) – Где размещать приёмники. Геометрии shapely считаются заданными в системе координатbuildings. По умолчанию — охватывающий прямоугольник зданий.height_column (
str | None, optional) – Столбец с высотами зданий в метрах. По умолчанию"height".storeys_column (
str | None, optional) – Столбец с числом этажей; используется (умноженный наstorey_height), если высоты нет.storey_height (
float, optional) – Высота одного этажа в метрах. По умолчанию 3.default_height (
float | None, optional) – Высота для зданий без обоих значений. Без неё такие здания пропускаются с предупреждением.terrain (
gpd.GeoDataFrame | str | os.PathLike | tuple | None, optional) –Высоты земли в метрах, одно из:
GeoDataFrame полигонов с высотой в
terrain_height_column(например, зоны высот); он растеризуется с ячейкамиterrain_cell, перекрывающиеся полигоны дают наибольшее значение, а места, не покрытые полигонами, считаются отсутствием данных;путь к GeoTIFF (нужен
rasterio);кортеж
(heights, transform, crs)из двумерного массива, аффинного преобразования(a, b, c, d, e, f)как в rasterio (x = a * col + c,y = e * row + f, на север, без поворота) и проецированной системы координат.
Растры задают систему координат расчёта; NaN отмечает отсутствие данных. Без рельефа земля ровная.
terrain_height_column (
str, optional) – Столбец высоты в GeoDataFrame рельефа. По умолчанию"height".terrain_cell (
float, optional) – Размер ячейки в метрах для растеризации GeoDataFrame рельефа. По умолчанию 5.grid_step (
float, optional) – Шаг приёмников в метрах. По умолчанию 2.time_step_min (
float, optional) – Шаг времени в минутах; сутки должны делиться на него без остатка. По умолчанию 10.day_step (
int, optional) – Для периода — моделировать каждыйday_step-й день (последний день периода включается всегда). По умолчанию 7.min_sun_elevation (
float, optional) – Положения солнца ниже этого угла (градусы) считаются отсутствием солнца, например чтобы, как в нормативах инсоляции, не учитывать низкое утреннее и вечернее солнце. По умолчанию 0.receiver_height (
float, optional) – Высота приёмников над землёй в метрах. По умолчанию 0.max_workers (
int | None, optional) – Число потоков (None— все ядра).
- Результат:
Точки приёмников в системе координат
buildings; точки внутри зданий исключаются. Столбцы:sun_hours: среднесуточное прямое солнце в часах (0для земли, куда прямое солнце не попадает ни в один моделируемый день);min_sun_hours: часы в худший день;max_continuous_hours: наибольшая непрерывная продолжительность инсоляции в худший день (наименьший из суточных наибольших отрезков), для которой нормативы инсоляции обычно задают минимум.
attrsсодержатdays(моделируемые даты) иday_length_hours(среднее время, когда солнце вышеmin_sun_elevation) и записывают сетку, поэтомуrasterize()превращает любой столбец вRaster.- Тип результата:
gpd.GeoDataFrame
- Исключение:
ValueError – При отсутствии системы координат, пустых входных данных, неизвестных столбцах высот, некорректном шаге времени или периоде.
ImportError – Если
terrain— путь к файлу, аrasterioне установлен.
Часы прямого солнца 21 марта и 21 июня 2026 года на территории 500 × 400 м (обведена), grid_step=2, time_step_min=10; приёмники растеризованы функцией objectnat.rasterize() в одной цветовой шкале. Высота зданий — storeys_count × 3 м.¶
Период 22 апреля – 22 августа 2026 года с day_step=7 (19 моделируемых дней), приёмники растеризованы objectnat.rasterize() в одной шкале. Слева: среднесуточные часы солнца. Справа: наибольшая непрерывная продолжительность инсоляции в худший день.¶
Та же территория 21 марта на ровной земле и с синтетической грядой высотой 50 м, вытянутой с запада на восток, с гребнем в 50 м к югу от территории, заданной массивом (heights, transform, crs) (пунктирные изолинии в метрах). Низкое солнце в равноденствие светит с юга. В южных 40 м территории, у подножия гряды, приёмники теряют в среднем 7 ч в сутки, и две трети из них вообще не получают прямого солнца; до 180 м севернее отдельные места всё ещё теряют 1–2 ч. Холм под самой территорией мало что меняет, потому что здания и приёмники поднимаются вместе с землёй.¶
Инсоляция фасадов¶
objectnat.get_facade_insolation() размещает точки вдоль каждой стены зданий, пересекающих area (внешних и дворовых стен), с шагом spacing метров, в 0,1 м перед стеной, на каждом этаже на высоте window_height над уровнем пола. На стенах, общих с соседним зданием, точек нет. Число этажей — значение этажности, если оно задано, иначе высота, делённая на storey_height. Точка учитывает солнце, только пока солнце находится перед её фасадом не ближе min_facade_angle градусов (по горизонтали) к плоскости фасада, а луч к солнцу не перекрыт другими зданиями или рельефом. Тени отбрасывают все здания из buildings, в том числе за пределами area.
В результате по одной точке на позицию на стене и этаж со столбцами building (метка индекса здания), floor (1 — первый этаж), height над землёй, facade_azimuth (направление, куда обращён фасад, в градусах по часовой стрелке от истинного севера), sun_hours, min_sun_hours и max_continuous_hours. С norm_hours добавляется meets_norm (max_continuous_hours >= norm_hours). Группировка точек по building и floor показывает, какие этажи и фасады не проходят по нормативу; сравнение расчётов с проектируемым зданием и без него показывает, какие окна оно затеняет.
- objectnat.get_facade_insolation(buildings, date, *, area=None, height_column='height', storeys_column=None, storey_height=3.0, default_height=None, terrain=None, terrain_height_column='height', terrain_cell=5.0, spacing=3.0, window_height=1.2, floors=None, time_step_min=10.0, day_step=7, min_sun_elevation=0.0, min_facade_angle=0.0, norm_hours=None, max_workers=None)[исходный код]¶
Часы прямого солнечного света на фасадах зданий по этажам: какие окна получают солнце, а какие нет.
Расчётные точки размещаются вдоль каждой стены зданий в
area(внешних и дворовых стен) с шагомspacingметров, на каждом этаже на высотеwindow_heightнад уровнем пола, прямо перед стеной. На стенах, общих с соседним зданием, точек нет. Точка освещена, если солнце находится перед её фасадом не ближеmin_facade_angleк плоскости фасада, а луч к солнцу проходит выше всех других стен и рельефа, как вget_insolation(). Тени отбрасывают все здания, в том числе за пределамиarea.- Параметры:
buildings (
geopandas.GeoDataFrame) – Контуры зданий с высотами, как вget_insolation().date (
datetime.date | str | tuple) – Один день или период(start, end), как вget_insolation().area (
gpd.GeoDataFrame | gpd.GeoSeries | shapely geometry | None, optional) – Здания, пересекающие эту территорию, получают точки на фасадах (геометрии shapely в системе координатbuildings). По умолчанию — все здания.height_column (
str|None) – Высоты зданий, как вget_insolation(). Число этажей — значение этажности, если оно задано, иначе высота, делённая наstorey_height(не меньше одного этажа).storeys_column (
str|None) – Высоты зданий, как вget_insolation(). Число этажей — значение этажности, если оно задано, иначе высота, делённая наstorey_height(не меньше одного этажа).storey_height (
float) – Высоты зданий, как вget_insolation(). Число этажей — значение этажности, если оно задано, иначе высота, делённая наstorey_height(не меньше одного этажа).default_height (
float|None) – Высоты зданий, как вget_insolation(). Число этажей — значение этажности, если оно задано, иначе высота, делённая наstorey_height(не меньше одного этажа).terrain (
GeoDataFrame|str|PathLike|tuple|None) – Высоты земли, как вget_insolation().terrain_height_column (
str) – Высоты земли, как вget_insolation().terrain_cell (
float) – Высоты земли, как вget_insolation().spacing (
float, optional) – Расстояние между точками вдоль стены в метрах; более короткие стены получают одну точку. По умолчанию 3.window_height (
float, optional) – Высота точек над уровнем каждого этажа в метрах. По умолчанию 1.2.floors (
Sequence[int] | None, optional) – Только эти этажи (1 — первый этаж). По умолчанию все этажи.time_step_min (
float) – Выборка положений солнца, как вget_insolation().day_step (
int) – Выборка положений солнца, как вget_insolation().min_sun_elevation (
float) – Выборка положений солнца, как вget_insolation().min_facade_angle (
float, optional) – Солнце ближе этого угла (градусы, по горизонтали) к плоскости фасада не учитывается. По умолчанию 0: учитывается любое солнце перед фасадом.norm_hours (
float | None, optional) – Требуемая непрерывная инсоляция в часах; добавляетmeets_norm(max_continuous_hours >= norm_hours).max_workers (
int | None, optional) – Число потоков (None— все ядра).
- Результат:
По одной точке на позицию на стене и этаж в системе координат
buildingsсо столбцамиbuilding(метка индекса здания),floor,height(над землёй),facade_azimuth(направление, куда обращён фасад, в градусах по часовой стрелке от истинного севера),sun_hours,min_sun_hoursиmax_continuous_hours(как вget_insolation()) и, приnorm_hours,meets_norm.attrsсодержатdaysиday_length_hours.- Тип результата:
gpd.GeoDataFrame
Точки на фасадах (spacing=3) 22 апреля 2026 года, окрашенные по наибольшей непрерывной продолжительности инсоляции, для 1, 5 и 10 этажей, и доля точек, получающих не меньше 2,5 ч непрерывного солнца, по этажам (norm_hours=2.5). Число точек на этаже указано в скобках. Порог 2,5 ч — пример; используйте норматив и расчётный день, которые относятся к проекту.¶
Ограничения¶
Крыши плоские. Скатные крыши, балконы, лоджии, карнизы и деревья не моделируются.
Точки на фасадах лежат перед внешней поверхностью стены; оконные откосы (толщина стены) не моделируются, поэтому углы солнца, которые срезал бы глубокий оконный проём, всё равно учитываются, если их не исключает
min_facade_angle.Учитывается только прямой солнечный свет; рассеянный свет неба и отражённый свет не учитываются, облачность игнорируется.
Результаты дискретны по времени (
time_step_min) и пространству (grid_step,spacing); непрерывный период может быть занижен или завышен на один шаг времени с каждого конца.Точность результата ограничена высотами зданий: высоты, полученные из этажности (
storeys×storey_height), могут отличаться от измеренных на несколько метров.