

If I open a MultiPolygon shapefile, the geometry is 'Polygon'
import fiona # creation of a MultiPolygon shapefile polysmultipolys = fiona.open("multipoly"multipol.shp") print len(polys) 3 # 3 polygons in the shapefile polysmultipolys.schema {'geometry': 'Polygon', 'properties': OrderedDict([(u'id', 'int:10')])} # creation of alen(multipolys) 1
Solution 1 with Fiona
MultiPolygonimport fiona from shapely.geometry import shape,mapping, Point, Polygon, MultiPolygon multi = MultiPolygon([shapefiona.open(i['geometry']"multipol.shp") for imultipol in= polys]multi.next() # schema# ofonly theone newfeature shapefile multin =the polys.schemashapefile mult['geometry'] = 'MultiPolygon' print multmultipol {'geometry': {'type': 'MultiPolygon', 'properties''coordinates': OrderedDict([[[[(u'id'-0.5275288092189501, 'int:10')]0.5569782330345711)} with, fiona.open("multipol-0.shp"11779769526248396, 'w'0.29065300896286816),driver='ESRI Shapefile'(-0.25608194622279135, schema=mult0.01920614596670933) as output: , output.write({'geometry':-0.709346991037132, mapping(multi-0.08834827144686286), 'properties':{'id':(-0.8629961587708066, 1}}0.18309859154929575)
Now if I open the new shapefile, the geometry is 'Polygon' but with only one feature (= list of the 3 polygons)
multipolys =, fiona.open("multipol.shp") multipolys-0.schema {'geometry': 'Polygon'734955185659411, 'properties':0.39820742637644047), OrderedDict([(u'id'-0.5275288092189501, 'int:10')])} len(multipolys0.5569782330345711) 1
Solution 1 expanding the list of polygons:
polygons = [poly for poly in multi for multi in]], multipolys] len[[(polygons) 3
And now you can apply the solution presented in More Efficient Spatial join in Python without QGIS, ArcGIS, PostGIS, etc (1)
points = [pt for pt in fiona0.open('points19974391805377723, 0.shp'060179257362355965)] # iterate through points for i, pt in enumerate(points): point =0.5480153649167734, shape(pt['geometry']0.1293213828425096) #iterate through polygons for j, poly in enumerate(polygons): 0.729833546734955, 0.03969270166453265), (0.8143405889884763, -0.13956466069142115), if(0.701664532650448, point-0.within(poly38540332906530095): , (0.4763124199743918, -0.5006402048655569), (0.26888604353393086, -0.4238156209987196), (0.18950064020486557, -0.2291933418693981), (0.19974391805377723, 0.060179257362355965)]], print[[(-0.3764404609475033, i-0.295774647887324), shape(points[i]['geometry'])-0.11523687580025621, #-0.3597951344430217), polygons[j] 1(-0.033290653008962945, POINT-0.5800256081946222), (-0.5889884763124211523687580025621, -0.177976952624847413572343149808) 3 POINT, (-0.49935979513444313072983354673495, -0.060179257362355858591549295774648) 5 POINT, (-0.376440460947503358898847631242, -0.47503201024327796927016645326505) 6 POINT, (-0.30985915492957756555697823303457, -0.63124199743918054750320102432779)
Solution 2 : recreating the MultiPolygon with Fiona
multi =, MultiPolygon([poly-0.3764404609475033, for-0.295774647887324)]]]}, poly'type': in'Feature', multi'id': for'0', multi'properties': inOrderedDict([(u'id', multipolys]1)])}
Fiona interprets the feature as a MultiPolygon and you can apply the solution presented in More Efficient Spatial join in Python without QGIS, ArcGIS, PostGIS, etc (1)
for i, pt in enumerate(points): point = shape(pt['geometry']) if point.within(multimulti['geometry')): print i, shape(points[i]['geometry']points[i]) ['geometry']) 1 POINT (-0.58898847631242 0.17797695262484) 3 POINT (0.4993597951344431 -0.06017925736235585) 5 POINT (-0.3764404609475033 -0.4750320102432779) 6 POINT (-0.3098591549295775 -0.6312419974391805)
This is a Supplement to the answer of xulnik.
import shapefile pts = shapefile.Reader("points.shp") polys = shapefile.Reader("multipol.shp") points = [pt.shape.__geo_interface__ for pt in pts.shapeRecords()] multi = [shapeshape(polpolys.shapeRecords()[0].shape.__geo_interface__) for# pol1 inpolygon print polymulti MULTIPOLYGON (((-0.shapeRecords5275288092189501 0.5569782330345711, -0.117797695262484 0.2906530089628682, -0.2560819462227913 0.01920614596670933, -0.7093469910371319 -0.08834827144686286, -0.8629961587708066 0.1830985915492958, -0.734955185659411 0.3982074263764405, -0.5275288092189501 0.5569782330345711)), ((0.1997439180537772 0.06017925736235596, 0.5480153649167734 0.1293213828425096, 0.729833546734955 0.03969270166453265, 0.8143405889884763 -0.1395646606914211, 0.701664532650448 -0.3854033290653009, 0.4763124199743918 -0.5006402048655569, 0.2688860435339309 -0.4238156209987196, 0.1895006402048656 -0.2291933418693981, 0.1997439180537772 0.06017925736235596)]), ((-0.3764404609475033 -0.295774647887324, -0.1152368758002562 -0.3597951344430217, -0.03329065300896294 -0.5800256081946222, -0.1152368758002562 -0.7413572343149808, -0.3072983354673495 -0.8591549295774648, -0.58898847631242 -0.6927016645326505, -0.6555697823303457 -0.4750320102432779, -0.3764404609475033 -0.295774647887324))) for i, pt in enumerate(points): point = shape(pt) if point.within(multi[0]multi): #first multipolygon print i, shape(points[i]) 1 POINT (-0.58898847631242 0.17797695262484) 3 POINT (0.4993597951344431 -0.06017925736235585) 5 POINT (-0.3764404609475033 -0.4750320102432779) 6 POINT (-0.3098591549295775 -0.6312419974391805)
The points 1,3,5,6 falls within the boundaries of the MultiPolygon
