Вычислить площадь полигона по заданным (x,y) координатам
у меня есть набор точек и я хотел бы знать, есть ли функция (для удобства и, вероятно, скорости), которая может вычислить область, заключенную в набор точек.
например:
x = np.arange(0,1,0.001)
y = np.sqrt(1-x**2)
points = zip(x,y)
дано points
площадь должна быть приблизительно равна (pi-2)/4
. Может быть, есть что-то от scipy, matplotlib, numpy, shapely и т. д. сделать это? Я не буду сталкиваться с отрицательными значениями для координат x или y... и они будут полигоны без какой-либо определенной функции.
EDIT:
точки, скорее всего, не будут в любом указанном порядке (по часовой стрелке или против часовой стрелки) и могут быть довольно сложными, поскольку они представляют собой набор координат utm из шейп-файла под набором границ
6 ответов
реализация шнурки формуле можно сделать Numpy
. Предполагая эти вершины:
import numpy as np
x = np.arange(0,1,0.001)
y = np.sqrt(1-x**2)
мы можем переопределить функцию в numpy, чтобы найти область:
def PolyArea(x,y):
return 0.5*np.abs(np.dot(x,np.roll(y,1))-np.dot(y,np.roll(x,1)))
и получаем результаты:
print PolyArea(x,y)
# 0.26353377782163534
избежать for
loop делает эту функцию ~50X быстрее, чем PolygonArea
:
%timeit PolyArea(x,y)
# 10000 loops, best of 3: 42 µs per loop
%timeit PolygonArea(zip(x,y))
# 100 loops, best of 3: 2.09 ms per loop.
синхронизация выполняется в ноутбуке Jupyter.
можно использовать шнурки формуле, например
def PolygonArea(corners):
n = len(corners) # of corners
area = 0.0
for i in range(n):
j = (i + 1) % n
area += corners[i][0] * corners[j][1]
area -= corners[j][0] * corners[i][1]
area = abs(area) / 2.0
return area
# examples
corners = [(2.0, 1.0), (4.0, 5.0), (7.0, 8.0)]
это работает только для простых многоугольников
Если у вас полигон с отверстиями : вычислить площадь внешнего кольца и subtrack области внутреннего кольца
Если у вас самопересекающиеся кольца: вы должны разложить их на простые сектора
анализируя ответ Махди, я пришел к выводу, что большая часть времени была потрачена на выполнение np.roll()
. Удалив необходимость рулона и все еще используя numpy, я получил время выполнения до 4-5μs за цикл по сравнению с 41μs Махди (для сравнения функция Махди заняла в среднем 37μs на моей машине).
def polygon_area(x,y):
correction = x[-1] * y[0] - y[-1]* x[0]
main_area = np.dot(x[:-1], y[1:]) - np.dot(y[:-1], x[1:])
return 0.5*np.abs(main_area + correction)
путем вычислять исправительный термин, и после этого отрезать массивы, никакая потребность свернуть или создать новое матрица.
критерии:
10000 iterations
PolyArea(x,y): 37.075µs per loop
polygon_area(x,y): 4.665µs per loop
время было сделано с помощью time
модуль time.clock()
в приведенном выше коде есть ошибка, так как он не принимает абсолютных значений на каждой итерации. Приведенный выше код всегда возвращает ноль. (Математически это разница между взятием подписанной области или продукта Клина и фактической областью http://en.wikipedia.org/wiki/Exterior_algebra.) Вот другой код.
def area(vertices):
n = len(vertices) # of corners
a = 0.0
for i in range(n):
j = (i + 1) % n
a += abs(vertices[i][0] * vertices[j][1]-vertices[j][0] * vertices[i][1])
result = a / 2.0
return result
Это намного проще, для регулярных полигонов:
import math
def area_polygon(n, s):
return 0.25 * n * s**2 / math.tan(math.pi/n)
так как формула ¼ n s2/tan(π / n). Учитывая количество сторон, n и длину каждой стороны, s
на основе
https://www.mathsisfun.com/geometry/area-irregular-polygons.html
def _area_(coords):
t=0
for count in range(len(coords)-1):
y = coords[count+1][1] + coords[count][1]
x = coords[count+1][0] - coords[count][0]
z = y * x
t += z
return abs(t/2.0)
a=[(5.09,5.8), (1.68,4.9), (1.48,1.38), (4.76,0.1), (7.0,2.83), (5.09,5.8)]
print _area_(a)
фишка в том, что первая координата должна быть последней.