def asShape(self): """returns geometry as shapefile._Shape() object""" shp = shapefile._Shape(shp_helper.shp_dict[self.geometryType.split( 'Geometry')[1].upper()]) if self.geometryType != ESRI_POINT: shp.points = self.json[JSON_CODE[self.geometryType]] else: shp.points = [[self.json[X], self.json[Y]]] # check if multipart, will need to fix if it is if any(isinstance(i, list) for i in shp.points): coords = [] part_indices = [0] + [len(i) for i in iter(shp.points)][:-1] ## for i in shp.points: ## coords.extend(i) ## shp.points = coords shp.parts = shapefile._Array('i', part_indices) else: shp.parts = shapefile._Array('i', [0]) if shp.shapeType not in (0, 1, 8, 18, 28, 31): XMin = min(coords[0] for coords in shp.points) YMin = min(coords[1] for coords in shp.points) XMax = max(coords[0] for coords in shp.points) YMax = max(coords[1] for coords in shp.points) shp.bbox = shapefile._Array('d', [XMin, YMin, XMax, YMax]) return shp
def shapely_to_pyshp(shapely_geometry): """This function converts a shapely geometry into a geojson and then into a pyshp object. Copied from Karim Bahgat's answer at: https://gis.stackexchange.com/questions/52705/how-to-write-shapely-geometries-to-shapefiles""" # first convert shapely to geojson try: shapelytogeojson = shapely.geometry.mapping except: import shapely.geometry shapelytogeojson = shapely.geometry.mapping geoj = shapelytogeojson(shapely_geometry) # create empty pyshp shape record = shapefile._Shape() # set shapetype if geoj["type"] == "Null": pyshp_type = 0 elif geoj["type"] == "Point": pyshp_type = 1 elif geoj["type"] == "LineString": pyshp_type = 3 elif geoj["type"] == "Polygon": pyshp_type = 5 elif geoj["type"] == "MultiPoint": pyshp_type = 8 elif geoj["type"] == "MultiLineString": pyshp_type = 3 elif geoj["type"] == "MultiPolygon": pyshp_type = 5 record.shapeType = pyshp_type # set points and parts if geoj["type"] == "Point": record.points = geoj["coordinates"] record.parts = [0] elif geoj["type"] in ("MultiPoint", "Linestring"): record.points = geoj["coordinates"] record.parts = [0] elif geoj["type"] in "Polygon": record.points = geoj["coordinates"][0] record.parts = [0] elif geoj["type"] in ("MultiPolygon", "MultiLineString"): index = 0 points = [] parts = [] for each_multi in geoj["coordinates"]: points.extend(each_multi[0]) parts.append(index) index += len(each_multi[0]) record.points = points record.parts = parts return record
def asShape(self): """returns geometry as shapefile._Shape() object""" shp = shapefile._Shape(shp_helper.shp_dict[self.geometryType.split('Geometry')[1].upper()]) if self.geometryType != 'esriGeometryPoint': shp.points = self.JSON[JSON_CODE[self.geometryType]] else: shp.points = [[self.JSON['x'], self.JSON['y']]] # check if multipart, will need to fix if it is if any(isinstance(i, list) for i in shp.points): coords = [] part_indices = [0] + [len(i) for i in iter(shp.points)][:-1] for i in shp.points: coords.extend(i) shp.points = coords shp.parts = shapefile._Array('i', part_indices) else: shp.parts = shapefile._Array('i', [0]) if shp.shapeType not in (0,1,8,18,28,31): XMin = min(coords[0] for coords in shp.points) YMin = min(coords[1] for coords in shp.points) XMax = max(coords[0] for coords in shp.points) YMax = max(coords[1] for coords in shp.points) shp.bbox = shapefile._Array('d', [XMin, YMin, XMax, YMax]) return shp
def geoj2shape(geoj): # create empty pyshp shape shape = pyshp._Shape() # set shapetype geojtype = geoj["type"] if geojtype == "Null": pyshptype = pyshp.NULL elif geojtype == "Point": pyshptype = pyshp.POINT elif geojtype == "LineString": pyshptype = pyshp.POLYLINE elif geojtype == "Polygon": pyshptype = pyshp.POLYGON elif geojtype == "MultiPoint": pyshptype = pyshp.MULTIPOINT elif geojtype == "MultiLineString": pyshptype = pyshp.POLYLINE elif geojtype == "MultiPolygon": pyshptype = pyshp.POLYGON shape.shapeType = pyshptype # set points and parts if geojtype == "Point": shape.points = [ geoj["coordinates"] ] shape.parts = [0] elif geojtype in ("MultiPoint","LineString"): shape.points = geoj["coordinates"] shape.parts = [0] elif geojtype in ("Polygon"): points = [] parts = [] index = 0 for ext_or_hole in geoj["coordinates"]: points.extend(ext_or_hole) parts.append(index) index += len(ext_or_hole) shape.points = points shape.parts = parts elif geojtype in ("MultiLineString"): points = [] parts = [] index = 0 for linestring in geoj["coordinates"]: points.extend(linestring) parts.append(index) index += len(linestring) shape.points = points shape.parts = parts elif geojtype in ("MultiPolygon"): points = [] parts = [] index = 0 for polygon in geoj["coordinates"]: for ext_or_hole in polygon: points.extend(ext_or_hole) parts.append(index) index += len(ext_or_hole) shape.points = points shape.parts = parts return shape
def geoj2shape(geoj): # create empty pyshp shape shape = pyshp._Shape() # set shapetype geojtype = geoj["type"] if geoj else "Null" if geojtype == "Null": pyshptype = pyshp.NULL elif geojtype == "Point": pyshptype = pyshp.POINT elif geojtype == "LineString": pyshptype = pyshp.POLYLINE elif geojtype == "Polygon": pyshptype = pyshp.POLYGON elif geojtype == "MultiPoint": pyshptype = pyshp.MULTIPOINT elif geojtype == "MultiLineString": pyshptype = pyshp.POLYLINE elif geojtype == "MultiPolygon": pyshptype = pyshp.POLYGON shape.shapeType = pyshptype # set points and parts if geojtype == "Point": shape.points = [geoj["coordinates"]] shape.parts = [0] elif geojtype in ("MultiPoint", "LineString"): shape.points = geoj["coordinates"] shape.parts = [0] elif geojtype in ("Polygon"): points = [] parts = [] index = 0 for ext_or_hole in geoj["coordinates"]: points.extend(ext_or_hole) parts.append(index) index += len(ext_or_hole) shape.points = points shape.parts = parts elif geojtype in ("MultiLineString"): points = [] parts = [] index = 0 for linestring in geoj["coordinates"]: points.extend(linestring) parts.append(index) index += len(linestring) shape.points = points shape.parts = parts elif geojtype in ("MultiPolygon"): points = [] parts = [] index = 0 for polygon in geoj["coordinates"]: for ext_or_hole in polygon: points.extend(ext_or_hole) parts.append(index) index += len(ext_or_hole) shape.points = points shape.parts = parts return shape
def shply_to_shape(shply_obj_list, out_path): """ outpath looks like this out_path = r"../geodata/split_up_poly_circle.shp" :param shply_obj_list: :param out_path: :return: """ pyshp_writer = shapefile.Writer() pyshp_writer.field("name") if len(shply_obj_list) > 1: for feature in shply_obj_list: geojson = mapping(feature) # create empty pyshp shape record = shapefile._Shape() # shapeType 3 is Mulitlinestring # shapeType 8 is Multipolygon # shapeType 5 is Polygon record.shapeType = 5 record.points = geojson["coordinates"][0] record.parts = [0] pyshp_writer._shapes.append(record) # add a list of attributes to go along with the shape pyshp_writer.record(["empty record"]) else: geojson = mapping(shply_obj_list[0]) # create empty pyshp shape record = shapefile._Shape() # shapeType 3 is Mulitlinestring # shapeType 8 is Multipolygon # shapeType 5 is Polygon record.shapeType = 5 record.points = geojson["coordinates"][0] record.parts = [0] pyshp_writer._shapes.append(record) # add a list of attributes to go along with the shape pyshp_writer.record(["empty record"]) pyshp_writer.save(out_path)
def geoj2shape(geoj): shape = pyshp._Shape() geojtype = geoj['type'] shape.shapeType = geoj2shape_format[geojtype] # Set points and parts # Points is a list of points, parts is the index of the start of each unique part if geojtype == 'Point': # Points don't have parts - just a list of coords shape.points = [geoj['cordinates']] shape.parts = [0] elif geojtype in ('MultiPoint', 'LineString'): # Either a set of unrelated points or a single line feature - no feature parts shape.points = geoj['coordinates'] shape.parts = [0] elif geojtype == 'Polygon': # Polygons can have exterior rings and interior holes - parts of a single feature points = [] parts = [] index = 0 for ext_or_hole in geoj['coordinates']: # Add the point list points.extend(ext_or_hole) # Track where each part starts in the point list parts.append(index) index += len(ext_or_hole) shape.points = points shape.parts = parts elif geojtype == 'MultiLineString': # Multiline string is a line with parts points = [] parts = [] index = 0 for linestring in geoj['coordinates']: points.extend(linestring) parts.append(index) index += len(linestring) shape.points = points shape.parts = parts elif geojtype == 'MultiPolygon': # Multipolygon is a multi-part polygon - multiple parts, each potentially with their own parts points = [] parts = [] index = 0 for Polygon in geoj['coordinates']: for ext_or_hole in polygon: points.extend(ext_or_hole) parts.append(index) index += len(ext_or_hole) shape.points = points shape.parts = parts return shape
def shapely_to_pyshp(shapely_geom): """ Shapely geometry to pyshp. Code adapted from https://gis.stackexchange.com/questions/52705/ how-to-write-shapely-geometries-to-shapefiles. Parameters: shapely_geom(shapely.geometry): shapely geometry to convert Returns: shapefile._Shape """ # first convert shapely to geojson geoj = shapely.geometry.mapping(shapely_geom) # create empty pyshp shape record = shapefile._Shape() # set shapetype pyshptype = GEOMETRY_TYPE[geoj["type"]] record.shapeType = pyshptype # set points and parts if geoj["type"] == "Point": record.points = geoj["coordinates"] record.parts = [0] elif geoj["type"] in ("MultiPoint", "LineString"): record.points = geoj["coordinates"] record.parts = [0] elif geoj["type"] == "Polygon": index = 0 points = [] parts = [] for eachmulti in geoj["coordinates"]: points.extend(eachmulti) parts.append(index) index += len(eachmulti) record.points = points record.parts = parts elif geoj["type"] in ("MultiPolygon", "MultiLineString"): index = 0 points = [] parts = [] for polygon in geoj["coordinates"]: for part in polygon: points.extend(part) parts.append(index) index += len(part) record.points = points record.parts = parts return record
def shapely_to_pyshp(shapelygeom): # first convert shapely to geojson try: shapelytogeojson = shapely.geometry.mapping except: import shapely.geometry shapelytogeojson = shapely.geometry.mapping geoj = shapelytogeojson(shapelygeom) # create empty pyshp shape record = shapefile._Shape() # set shapetype if geoj["type"] == "Null": pyshptype = 0 elif geoj["type"] == "Point": pyshptype = 1 elif geoj["type"] == "LineString": pyshptype = 3 elif geoj["type"] == "Polygon": pyshptype = 5 elif geoj["type"] == "MultiPoint": pyshptype = 8 elif geoj["type"] == "MultiLineString": pyshptype = 3 elif geoj["type"] == "MultiPolygon": pyshptype = 5 record.shapeType = pyshptype # set points and parts if geoj["type"] == "Point": record.points = geoj["coordinates"] record.parts = [0] elif geoj["type"] in ("MultiPoint", "Linestring"): record.points = geoj["coordinates"] record.parts = [0] elif geoj["type"] in ("Polygon"): record.points = geoj["coordinates"][0] record.parts = [0] elif geoj["type"] in ("MultiPolygon", "MultiLineString"): index = 0 points = [] parts = [] for eachmulti in geoj["coordinates"]: points.extend(eachmulti[0]) parts.append(index) index += len(eachmulti[0]) record.points = points record.parts = parts return record
roads_intersect = roads_london_shply.intersection(clip_shply) # only export linestrings, shapely also created points if roads_intersect.geom_type == "LineString": roads_clip_list.append(roads_intersect) # open writer to write our new shapefile too pyshp_writer = shapefile.Writer() # create new field pyshp_writer.field("name") # convert our shapely geometry back to pyshp, record for record for feature in roads_clip_list: geojson = mapping(feature) # create empty pyshp shape record = shapefile._Shape() # shapeType 3 is linestring record.shapeType = 3 record.points = geojson["coordinates"] record.parts = [0] pyshp_writer._shapes.append(record) # add a list of attributes to go along with the shape pyshp_writer.record(["empty record"]) # save to disk pyshp_writer.save(r"../geodata/roads_clipped2.shp")
# only export linestrings, shapely also created points if roads_intersect.geom_type == "LineString": roads_clip_list.append(roads_intersect) # open writer to write our new shapefile too pyshp_writer = shapefile.Writer() # create new field pyshp_writer.field("name") # convert our shapely geometry back to pyshp, record for record for feature in roads_clip_list: geojson = mapping(feature) # create empty pyshp shape record = shapefile._Shape() # shapeType 3 is linestring record.shapeType = 3 record.points = geojson["coordinates"] record.parts = [0] pyshp_writer._shapes.append(record) # add a list of attributes to go along with the shape pyshp_writer.record(["empty record"]) # save to disk pyshp_writer.save(r"../geodata/roads_clipped.shp") # setup matplotlib figure that will display the results fig = pyplot.figure(1, figsize=SIZE, dpi=90, facecolor="white")
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
def shape_from_shapely_to_pyshp(shapely_shape, keep_holes=True): """ convert shape object in the shapely object to pyshp object (shapefile) Note however: the function will NOT handle any interior polygon holes if there are any, it simply ignores them. :param shapely_shape: the shapely object :return: object if successful, False otherwise """ # first convert shapely to geojson try: shapelytogeojson = shapely.geometry.mapping except: import shapely.geometry shapelytogeojson = shapely.geometry.mapping geoj = shapelytogeojson(shapely_shape) # create empty pyshp shape record = shapefile._Shape() # set shapetype if geoj["type"] == "Null": pyshptype = 0 elif geoj["type"] == "Point": pyshptype = 1 elif geoj["type"] == "LineString": pyshptype = 3 elif geoj["type"] == "Polygon": pyshptype = 5 elif geoj["type"] == "MultiPoint": pyshptype = 8 elif geoj["type"] == "MultiLineString": pyshptype = 3 elif geoj["type"] == "MultiPolygon": pyshptype = 5 record.shapeType = pyshptype # set points and parts if geoj["type"] == "Point": record.points = geoj["coordinates"] record.parts = [0] elif geoj["type"] in ("MultiPoint", "Linestring"): record.points = geoj["coordinates"] record.parts = [0] elif geoj["type"] in ("Polygon"): if keep_holes is False: record.points = geoj["coordinates"][0] record.parts = [0] else: # need to consider the holes all_coordinates = geoj["coordinates"] parts_count = len(all_coordinates) # print(parts_count) record.parts = [] for i in range(0, parts_count): # record.points = geoj["coordinates"][0] record.parts.append(len(record.points)) record.points.extend(all_coordinates[i]) elif geoj["type"] in ("MultiPolygon", "MultiLineString"): if keep_holes is False: index = 0 points = [] parts = [] for eachmulti in geoj["coordinates"]: points.extend(eachmulti[0]) parts.append(index) index += len(eachmulti[0]) record.points = points record.parts = parts else: # need to consider the holes all_polygons_coor = geoj["coordinates"] polygon_count = len(all_polygons_coor) # print(parts_count) record.parts = [] for i in range(0, polygon_count): for j in range(0, len(all_polygons_coor[i])): # record.points = geoj["coordinates"][0] record.parts.append(len(record.points)) record.points.extend(all_polygons_coor[i][j]) # index = 0 # points = [] # parts = [] # skip = 1 # for eachmulti in geoj["coordinates"]: # if skip ==1 : # skip = skip + 1 # continue # # points.extend(eachmulti[0]) # parts.append(index) # index += len(eachmulti[0]) # record.points = points # record.parts = parts return record