Tạo Shapely MultiPolygons từ shapefile MultiPolygons


12

Tôi đang đọc một shapefile bằng Fiona:

with fiona.open('data/boroughs/boroughs_n.shp') as source:
   mpolys = [p for p in source]
candidate = polys[0]['geometry']

điều này mang lại cho tôi một lệnh có chứa danh sách các danh sách tọa độ và nhập 'MultiPolygon' Tuy nhiên, tôi không chắc chắn cách sử dụng dữ liệu tọa độ để tạo Shapely MultiPolygon, vì nó yêu cầu a sequence of exterior ring and hole list tuples: [((a1, ..., aM), [(b1, ..., bN), ...]), ...].

Có cách nào "chính xác" để làm việc này không, sử dụng Fiona và Shapely?

Câu trả lời:


18

Bạn có thể sử dụng chức năng hình dạng của Shapely:

from shapely.geometry import shape
c = fiona.open('data/boroughs/boroughs_n.shp')
pol = c.next()
geom = shape(pol['geometry'])

và MultiPolygon là một danh sách các Đa giác, vì vậy

Multi = MultiPolygon([shape(pol['geometry']) for pol in fiona.open('data/boroughs/boroughs_n.shp')]) 

Ví dụ với một trong những dữ liệu của tôi:

# the dictionaries
for pol in fiona.open('poly.shp'):
print pol['geometry']

{'type': 'Polygon', 'coordinates': [[(249744.23153029341, 142798.16434689672),   (250113.79108725351, 142132.95714436853), (250062.62130244367, 141973.76225829343), (249607.77877080048, 141757.71205576291), (249367.77424759799, 142304.68402918623), (249367.77424759799, 142304.68402918623), (249744.23153029341, 142798.16434689672)]]}
{'type': 'Polygon', 'coordinates': [[(249175.78991730965, 142292.53526406409), (249367.77424759799, 142304.68402918623), (249607.77877080048, 141757.71205576291), (249014.45396077307, 141876.13484290778), (249175.78991730965, 142292.53526406409)]]}
{'type': 'Polygon', 'coordinates': [[(249026.74622412826, 142549.13626160321), (249223.42243781092, 142496.89414234375), (249175.78991730965, 142292.53526406409), (249026.74622412826, 142549.13626160321)]]}
...

 # MultiPolygon from the list of Polygons
 Multi = MultiPolygon([shape(pol['geometry']) for pol in fiona.open('poly.shp')])
 Multi.wkt
'MULTIPOLYGON (((249744.2315302934148349 142798.1643468967231456, 250113.7910872535139788 142132.9571443685272243, 250062.6213024436729029 141973.7622582934272941, 249607.7787708004761953 141757.7120557629095856, 249367.7742475979903247 142304.6840291862317827, 249367.7742475979903247 142304.6840291862317827, 249744.2315302934148349 142798.1643468967231456)), ((249175.7899173096520826 142292.5352640640921891, 249367.7742475979903247 142304.6840291862317827, 249607.7787708004761953 141757.7120557629095856, 249014.4539607730694115 141876.1348429077770561, 249175.7899173096520826 142292.5352640640921891)), ((249026.7462241282628383 142549.1362616032129154, 249223.4224378109211102 142496.8941423437499907, 249175.7899173096520826 142292.5352640640921891, 249026.7462241282628383 142549.1362616032129154)), ((249244.9338986824732274 142733.5202119307068642, 249744.2315302934148349 142798.1643468967231456, 249367.7742475979903247 142304.6840291862317827, 249367.7742475979903247 142304.6840291862317827, 249367.7742475979903247 142304.6840291862317827, 249175.7899173096520826 142292.5352640640921891, 249223.4224378109211102 142496.8941423437499907, 249244.9338986824732274 142733.5202119307068642)), ((249870.8182051893090829 142570.3083320840960369, 250034.3015973484434653 142613.6706442178401630, 250152.6146321419219021 142438.5058914067049045, 250015.3392731740023009 142310.1704097116598859, 249870.8182051893090829 142570.3083320840960369)))'

xem thêm Nối hỗ trợ cho MultiPolygons trong shapefiles


Điều đó đã hoạt động hoàn hảo, tôi chỉ phải chèn một số xử lý khi vẽ đồ thị bằng Descartes vì ​​một số hình dạng trong tệp là Đa giác, không phải MultiPolygon. Cảm ơn!
urschrei

1
Không thể nói nó tốt hơn bản thân mình, gen!
sgillies

3

Nếu tốc độ là một vấn đề, thì việc tạo đa giác từ tọa độ thô sẽ nhanh hơn.

Tốc độ này nhanh hơn khoảng 5 lần so với giải pháp được đề xuất trước đây là trước tiên phải tạo một số đối tượng đa giác và sau đó tạo đối tượng đa đường từ những đối tượng đó.

Đây là cách làm:

# first retrieve the coordinates from your geojson dictionary
rawcoords = candidate["coordinates"]

# define the conversion function
def PrepCoordsForShapely(rawcoords):
    preppedcoords = []
    #according to the geojson specs, a multipolygon is a list of linear rings, so we loop each
    for eachpolygon in rawcoords:
        #the first linear ring is the coordinates of the polygon, and shapely needs it to be a tuple
        tupleofcoords = tuple(eachpolygon[0])
        #the remaining linear rings, if any, are the coordinates of inner holes, and shapely needs these to be nested in a list
        if len(eachpolygon) > 1:
            listofholes = list(eachpolygon[1:])
        else:
            listofholes = []
        #shapely defines each polygon in a multipolygon with the polygoon coordinates and the list of holes nested inside a tuple
        eachpreppedpolygon = (tupleofcoords, listofholes)
        #so append each prepped polygon to the final multipolygon list
        preppedcoords.append(eachpreppedpolygon)
    #finally, the prepped coordinates need to be nested inside a list in order to be used as a star-argument for the MultiPolygon constructor.
    return [preppedcoords]

# use the function to prepare coordinates for MultiPolygon
preppedcoords = PrepCoordsForShapely(rawcoords)
# use the prepped coordinates as a star-argument for the MultiPolygon constructor
shapelymultipolygon = MultiPolygon(*preppedcoords)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.