Рассчитать площадь полигона по заданным (х, у) координатам

Мне потребовалось много времени, чтобы выяснить, но, наконец, вот простой способ перечислить содержимое подпапки в ведро S3 с помощью boto3. Надеюсь, что это поможет

prefix = "folderone/foldertwo/"
s3 = boto3.resource('s3')
bucket = s3.Bucket(name="bucket_name_here")
FilesNotFound = True
for obj in bucket.objects.filter(Prefix=prefix):
     print('{0}:{1}'.format(bucket.name, obj.key))
     FilesNotFound = False
if FilesNotFound:
     print("ALERT", "No file in {0}/{1}".format(bucket, prefix))
29
задан pbreach 28 June 2014 в 15:04
поделиться

7 ответов

Реализация формулы шнурка может быть выполнена в 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 цикл делает эту функцию примерно в 50 раз быстрее, чем 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.

63
ответ дан Mahdi 28 June 2014 в 15:04
поделиться

Ответ maxb дает хорошую производительность, но может легко привести к потере точности, когда значения координат или количество точек велики. Это может быть смягчено простым сдвигом координат:

def polygon_area(x,y):
    # coordinate shift
    x_ = x - x.mean()
    y_ = y - y.mean()
    # everything else is the same as maxb's code
    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)

Например, общей системой географической привязки является UTM, которая может иметь (x, y) координаты (488685.984, 7133035.984). Произведение этих двух значений равно 3485814708748.448. Вы можете видеть, что этот единственный продукт уже на грани точности (он имеет то же количество десятичных разрядов, что и входные данные). Добавление лишь нескольких из этих продуктов, не говоря уже о тысячах, приведет к потере точности.

Простой способ смягчить это - сдвинуть многоугольник от больших положительных координат к чему-то ближе к (0,0), например, вычитая центроид, как в коде выше. Это помогает двумя способами:

,
    ,
  1. . Он исключает коэффициент x.mean() * y.mean() для каждого продукта
  2. . В каждом точечном произведении получается сочетание положительных и отрицательных значений, что в значительной степени отменяет .

Смещение координат не изменяет общую площадь, оно просто делает расчет более устойчивым в численном отношении.

3
ответ дан Trenton 28 June 2014 в 15:04
поделиться

Анализируя ответ Махди, я пришел к выводу, что большую часть времени проводил, занимаясь np.roll(). Убрав необходимость в броске и все еще используя numpy, я сократил время выполнения до 4-5 мксек на цикл по сравнению с 41 мкс Махди (для сравнения, функция Махди в среднем занимала 37 мкс на моей машине).

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()

4
ответ дан maxb 28 June 2014 в 15:04
поделиться

Вы можете использовать формулу шнурка , например,

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)]

Это работает только для простых многоугольников


  • Если у вас есть многоугольник с отверстиями : вычислите площадь внешнего кольца и вычтите области внутренних колец

  • Если у вас есть самопересекающиеся кольца : их нужно разложить на простые сектора

26
ответ дан Nikos Athanasiou 28 June 2014 в 15:04
поделиться

В приведенном выше коде есть ошибка, так как он не принимает абсолютные значения на каждой итерации. Приведенный выше код всегда будет возвращать ноль. (Математически это разница между взятием продукта со знаком или клина и реальной площадью 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
2
ответ дан Chris Judge 28 June 2014 в 15:04
поделиться

Это гораздо проще для правильных многоугольников:

import math

def area_polygon(n, s):
    return 0.25 * n * s**2 / math.tan(math.pi/n)

, поскольку формула ¼ n s2 / tan (π / n). Учитывая количество сторон, n, и длину каждой стороны, s

1
ответ дан Bizarre 28 June 2014 в 15:04
поделиться

На основании

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)

Хитрость в том, что первая координата также должна быть последней.

0
ответ дан Takis Tsiberis 28 June 2014 в 15:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: