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