Пример #1
0
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