Python / shapely: вычислить площадь полигона в плоских единицах (например, квадратные метры)

Я использую Python 3.4 и shapely 1.3.2 для создания полигонального объекта из списка пар координат long/lat, которые я преобразую в хорошо известную текстовую строку для их анализа. Такой многоугольник может выглядеть так:

POLYGON ((-116.904 43.371, -116.823 43.389, -116.895 43.407, -116.908 43.375, -116.904 43.371))

поскольку shapely не обрабатывает никаких проекций и реализует все объекты геометрии в картезианском пространстве, вызывая метод area на этом многоугольнике, например:

poly.area

дает мне площадь этого многоугольника в единице квадратных градусов. Чтобы получить площадь в плоской единице, такой как квадратные метры, я думаю, что мне придется преобразовать координаты многоугольника, используя другую проекцию (какую?).

Я несколько раз читал, что библиотека pyproj должна предоставить способ сделать это. Используя pyproj, есть ли способ преобразовать весь фигурный полигональный объект в другую проекцию, а затем вычислить площадь?

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

до сих пор я нашел только этот пример: http://all-geo.org/volcan01010/2012/11/change-coordinates-with-pyproj/

что означало бы разбиение каждого полигонального объекта на его внешние и, если есть, внутренние кольца, захватите координаты, преобразуйте каждую пару координат в другую проекцию и перестройте полигональный объект, а затем вычислите его площадь (какая единица тогда?). Это выглядит как решение, но не очень практическое.

идеи получше?

2 ответов


хорошо, я, наконец, сделал это с набором инструментов базовой карты библиотеки matplotlib. Я объясню, как это работает, может быть, это будет полезно для кого-нибудь.

1. Загрузите и установите библиотеку matplotlib в свою систему. http://matplotlib.org/downloads.html

для двоичных файлов Windows я рекомендую использовать эту страницу: http://www.lfd.uci.edu / ~gohlke / pythonlibs / #matplotlib Остерегайтесь намека, который говорит:

требуется numpy, dateutil, pytz, pyparsing, шесть и, возможно, подушка, pycairo, торнадо, wxPython, в, pyside, pyqt, в Ghostscript, программы, видео, mencoder, avconv или imagemagick.

следовательно, если вы еще не установлены в вашей системе, вам нужно загрузить и установить numpy, dateutil, pytz, pyparsing и six, а также для правильной работы matplotlib (для пользователей Windows: все они могут быть найдены на странице, для пользователей Linux менеджер пакетов python "pip" должен сделать трюк.)

2. Загрузите и установите инструментарий "базовая карта" для matplotlib. Либо от http://matplotlib.org/basemap/users/installing.html или бинарники для Windows и отсюда: http://www.lfd.uci.edu / ~gohlke / pythonlibs / #базовая карта

3. Сделайте проекцию в своем коде Python:

#Import necessary libraries
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np

#Coordinates that are to be transformed
long = -112.367
lat = 41.013

#Create a basemap for your projection. Which one you use is up to you.
#Some examples can be found at http://matplotlib.org/basemap/users/mapsetup.html
m = Basemap(projection='sinu',lon_0=0,resolution='c')

#Project the coordinates:
projected_coordinates = m(long,lat)

выход:

projected_coordinates (10587117.191355567, 14567974.064658936)

просто. Теперь, при использовании проецируемых координат для построения многоугольника с shapely, а затем вычисления площади с помощью метода площади shapely, вы получите площадь в единице квадратных метров (в соответствии с используемой проекцией). Чтобы получить квадратные километры, разделите на 10^6.

Edit: я изо всех сил старался не преобразовывать только отдельные координаты, но и целые геометрические объекты, такие как полигоны, когда они уже были даны как фигурные объекты, а не через их необработанные координаты. Это означало написать много кода для

  • получить координаты внешнего кольца многоугольника
  • определите, имеет ли многоугольник отверстия, и если да, обрабатывайте каждое отверстие отдельно
  • преобразование каждой пары координат внешнего кольца и отверстий
  • соберите все это вместе и создайте полигональный объект с проецируемым координаты
  • и это только для полигонов... добавьте еще больше циклов для мультиполигонов и geometrycollections

затем я наткнулся на эту часть shapely документации, которая делает вещи намного проще: http://toblerity.org/shapely/manual.html#shapely.ops.transform

когда проекционная карта установлена, например, как это сделано выше:

m = Basemap(width=1,height=1, resolution='l',projection='laea',lat_ts=50,lat_0=50,lon_0=-107.)

тогда можно преобразовать любую геометрию формы объект, использующий эту проекцию через:

from shapely.ops import transform
projected_geometry = transform(m,geometry_object)

преобразовать в радианы и предполагая, что Земля-идеальная сфера с радиусом 6370Km:

p = np.массив([[-116.904,43.371],[-116.823, 43.389],[-116.895,43.407],[-116.908,43.375],[-116.904,43.371]])

poly = многоугольник(np.radians (p))

Поли.область =4,468737548271707 e-07

Поли.площадь*6370**2 =18.132751662246623