shapefile MultiPolygon에서 Shapely MultiPolygon 작성


12

Fiona를 사용하여 shapefile을 읽고 있습니다.

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

이것은 좌표 목록과 'MultiPolygon'유형을 포함하는 dict를 제공하지만, 좌표 데이터를 사용하여 Shapely MultiPolygon을 만드는 방법을 잘 모르겠습니다. a sequence of exterior ring and hole list tuples: [((a1, ..., aM), [(b1, ..., bN), ...]), ...].

Fiona와 Shapely를 사용하여이를 수행하는 '올바른'방법이 있습니까?

답변:


18

Shapely의 모양 기능을 사용할 수 있습니다.

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

MultiPolygon은 다각형의 목록입니다.

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

내 데이터 중 하나의 예 :

# 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)))'

shapefile에서 MultiPolygon에 대한 지원 추가 참조


그것은 완벽하게 작동했습니다. 파일의 일부 모양이 MultiPolygon이 아닌 Polygon이기 때문에 Descartes를 사용하여 플로팅 할 때 약간의 처리를 삽입해야했습니다. 감사!
urschrei

1
나 자신에게 더 잘 말할 수 없었습니다, 유전자!
sgillies

3

속도가 문제가되면 원시 좌표에서 다중 다각형을 만드는 것이 더 빠릅니다.

이것은 먼저 여러 다각형 객체를 생성 한 다음 그로부터 다중 다각형 객체를 생성해야하는 이전에 제안 된 솔루션보다 약 5 배 빠릅니다.

방법은 다음과 같습니다.

# 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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.