Площадь полигона: формула шнуровки

Урок выводит и реализует формулу шнуровки — способ найти площадь произвольного многоугольника, зная только координаты его вершин.

Формула шнуровки (формула Гаусса, shoelace) вычисляет площадь простого многоугольника как полусумму перекрёстных произведений координат соседних вершин.

Площадь региона — базовый показатель: плотность населения, доля леса, размер участка. Если регион задан полигоном, его площадь нельзя «измерить линейкой» — её считают по координатам. Формула шнуровки делает это для любого простого (несамопересекающегося) многоугольника: хоть треугольника, хoть контура страны с тысячей вершин.

Откуда «шнуровка»

Площадь равна половине модуля суммы $\sum (x_i y_{i+1} - x_{i+1} y_i)$ по всем рёбрам. Если выписать координаты столбиком и перемножать накрест — вниз-вправо со знаком плюс, вниз-влево со знаком минус, — линии перемножений напоминают шнуровку ботинка. Отсюда название.

$S = \frac{1}{2}\left|\sum_{i=0}^{n-1}\left(x_i\,y_{i+1} - x_{i+1}\,y_i\right)\right|$

Индекс $i+1$ берётся по кругу: после последней вершины снова идёт первая.

Реализация

def polygon_area(poly):
    n = len(poly)
    s = 0.0
    for i in range(n):
        x1, y1 = poly[i]
        x2, y2 = poly[(i + 1) % n]  # следующая, замыкая на первую
        s += x1 * y2 - x2 * y1
    return abs(s) / 2

# Прямоугольник 4 x 3
rect = [(0, 0), (4, 0), (4, 3), (0, 3)]
print(f"Прямоугольник: {polygon_area(rect)}")

# Треугольник с основанием 4 и высотой 3 -> площадь 6
tri = [(0, 0), (4, 0), (2, 3)]
print(f"Треугольник:   {polygon_area(tri)}")

# L-образный полигон (площадь 12: квадрат 4x4 минус вырез 2x2)
L = [(0, 0), (4, 0), (4, 2), (2, 2), (2, 4), (0, 4)]
print(f"Фигура L:      {polygon_area(L)}")

Вывод:

Прямоугольник: 12.0
Треугольник:   6.0
Фигура L:      12.0

Все три ответа совпадают с геометрической проверкой: $4 \times 3 = 12$, $\frac{1}{2}\cdot 4 \cdot 3 = 6$, а L — это квадрат $4\times4=16$ минус вырез $2\times2=4$, итого $12$.

Как работает под капотом

Каждое слагаемое $x_i y_{i+1} - x_{i+1} y_i$ — это удвоенная площадь треугольника, образованного началом координат и ребром $i \to i{+}1$. Суммируя по контуру, мы складываем эти треугольники со знаком: части полигона учитываются плюсом, «вычитаемые» части (как вырез) — минусом, и всё лишнее взаимно сокращается. Знак суммы (до взятия модуля) кодирует направление обхода: против часовой стрелки — плюс, по часовой — минус. Это используют, чтобы определить ориентацию контура. Важная оговорка: для географических координат в градусах формула даст «квадратные градусы» — бессмыслицу; сначала полигон проецируют в метры (UTM), и только там площадь получается в честных квадратных метрах.

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

  • Не замкнуть контур. Оператор (i + 1) % n обязателен, иначе потеряется последнее ребро.
  • Забыть модуль и делить на 2. Без модуля знак зависит от направления обхода; без деления получится удвоенная площадь.
  • Считать площадь в градусах. Для Земли сперва проецируйте в метры — иначе число не имеет физического смысла.

Почему именно перекрёстное произведение

За формулой шнуровки стоит красивая геометрия, и понимание её спасает от механического заучивания. Величина $x_i y_{i+1} - x_{i+1} y_i$ — это векторное произведение двух радиус-векторов из начала координат к концам ребра, а оно равно удвоенной площади треугольника «начало координат — две вершины ребра», взятой со знаком. Обходя контур, мы как веером заметаем эти треугольники от точки отсчёта; те, что «лишние» (вне фигуры), при обходе заметаются в обратную сторону и входят с минусом, аккуратно вычитаясь. В итоге, где бы ни лежало начало координат — хоть внутри полигона, хоть далеко снаружи, — сумма всегда даёт верную площадь самой фигуры. Это свойство «независимости от точки отсчёта» — то, что делает формулу надёжной.

Из той же конструкции бесплатно следует тест ориентации. Положительная сумма (до модуля) означает обход против часовой стрелки, отрицательная — по часовой. В GeoJSON по соглашению внешнее кольцо полигона обходят против часовой, а внутренние «дырки» — по часовой; проверив знак, можно понять, контур это или вырез, и автоматически починить неправильно ориентированные данные. Для полигона с дырками площадь считают как площадь внешнего кольца минус площади внутренних — и знаки формулы делают это вычитание автоматически, если кольца ориентированы по соглашению.

Итог

  • Формула шнуровки: $S = \frac{1}{2}\left|\sum (x_i y_{i+1} - x_{i+1} y_i)\right|$.
  • Работает для любого простого многоугольника по координатам вершин.
  • Знак суммы (до модуля) показывает направление обхода контура.
  • На Земле площадь считают после проекции в метры, не в градусах.
Проверьте себя
1. Что вычисляет формула шнуровки?
AПериметр
BПлощадь простого многоугольника по координатам вершин
CРасстояние между точками
DЦентр фигуры
2. Что показывает знак суммы до взятия модуля?
AРазмер фигуры
BНаправление обхода вершин (по или против часовой стрелки)
CЧисло вершин
DЦвет полигона
3. Почему площадь земного полигона нельзя считать прямо в градусах?
AМожно, разницы нет
BПолучатся бессмысленные «квадратные градусы»; нужно сперва проецировать в метры
CГрадусы нельзя умножать
DФормула не работает на сфере вообще