def shape_from_pyshp_to_shapely(pyshp_shape, threshold): """ convert pyshp object to shapely object :param pyshp_shape: pyshp (shapefile) object :return: shapely object if successful, False otherwise """ parts_index = pyshp_shape.parts if len(parts_index) < 2: # Create a polygon with no holes record = Polygon(pyshp_shape.points) else: # Create a polygon with one or several holes seperate_parts = [] parts_index.append(len(pyshp_shape.points)) for i in range(0, len(parts_index) - 1): points = pyshp_shape.points[parts_index[i]:parts_index[i + 1]] seperate_parts.append(points) # if list(parts_index)==[0,121,130,135,140]: # debug = 1 # assuming the first part is exterior # exterior = seperate_parts[0] # assuming the first part is exterior # interiors = [seperate_parts[i] for i in range(1,len(seperate_parts))] # assuming the last part is exterior # exterior = seperate_parts[len(parts_index)-2] # interiors = [seperate_parts[i] for i in range(0,len(seperate_parts)-2)] all_polygons = [] length = len(seperate_parts) flag = 0 for i in range(length - 1): if len(seperate_parts[flag]) > len(seperate_parts[i + 1]): flag = flag else: flag = i + 1 threshold = len(seperate_parts[flag]) - 1 while (len(seperate_parts) > 0): print("the first polygon has %d points" % len(seperate_parts[0])) #if shapefile.signed_area(seperate_parts[0]) < 0: # the area of ring is clockwise, it's not a hole #if shapefile.signed_area(seperate_parts[0]) > 0: if len(seperate_parts[0]) > threshold: print("the exterior polygon has %d points" % len(seperate_parts[0])) exterior = tuple(seperate_parts[0]) seperate_parts.remove(seperate_parts[0]) # find all the holes attach to the first exterior interiors = [] holes_points = [] for points in seperate_parts: #if shapefile.signed_area(points) >= 0: # the value >= 0 means the ring is counter-clockwise, then they form a hole if len(points) < threshold: interiors.append(tuple(points)) holes_points.append(points) # remove the parts which are holes for points in holes_points: seperate_parts.remove(points) # else: # break if len(interiors) < 1: interiors = None else: interiors = tuple(interiors) polygon = Polygon(shell=exterior, holes=interiors) all_polygons.append(polygon) else: seperate_parts.remove(seperate_parts[0]) if len(all_polygons) > 1: record = MultiPolygon(polygons=all_polygons) else: record = all_polygons[0] shapelytogeojson = shapely.geometry.mapping geoj = shapelytogeojson(record) # create empty pyshp shape record = shapefile._Shape() record.points = geoj["coordinates"][0] record.shapeType = 5 record.parts = [0] # # plot shape for checking # from matplotlib import pyplot as plt # from descartes import PolygonPatch # from math import sqrt # # from shapely.geometry import Polygon, LinearRing # # from shapely.ops import cascaded_union # BLUE = '#6699cc' # GRAY = '#999999' # # # plot these two polygons separately # fig = plt.figure(1, dpi=90) #figsize=SIZE, # ax = fig.add_subplot(111) # poly1patch = PolygonPatch(record, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2) # # poly2patch = PolygonPatch(polygon2, ec=BLUE, alpha=0.5, zorder=2) # ax.add_patch(poly1patch) # # ax.add_patch(poly2patch) # boundary = record.bounds # xrange = [boundary[0], boundary[2]] # yrange = [boundary[1], boundary[3]] # ax.set_xlim(*xrange) # # ax.set_xticks(range(*xrange) + [xrange[-1]]) # ax.set_ylim(*yrange) # # ax.set_yticks(range(*yrange) + [yrange[-1]]) # # ax.set_aspect(1) # # plt.show() return record