def download_by_boundary(input_boundary, output_osm, epsg, area_threshold=None, GetUrl=True): """ Download data from OSM using a bounding box """ import os from decimal import Decimal from gasp.prop.feat import feat_count from gasp.prop.ext import get_extent from gasp.web import get_file # Check number of features number_feat = feat_count(input_boundary) if number_feat != 1: raise ValueError( ('Your boundary has more than one feature. ' 'Only feature classes with one feature are allowed.')) # Check boundary area if area_threshold: from gasp.cpu.gdl import area_to_dic d_area = area_to_dic(input_boundary) if d_area[0] > area_threshold: raise ValueError('{} has more than than {} square meters'.format( os.path.basename(input_boundary), str(area_threshold))) # Get boundary extent left, right, bottom, top = get_extent(input_boundary, gisApi='ogr') if epsg != 4326: from gasp.to.geom import create_point from gasp.mng.prj import project_geom bottom_left = project_geom(create_point(left, bottom, api='ogr'), epsg, 4326, api='ogr') top_right = project_geom(create_point(right, top, api='ogr'), epsg, 4326, api='ogr') left, bottom = bottom_left.GetX(), bottom_left.GetY() right, top = top_right.GetX(), top_right.GetY() bbox_str = ','.join([str(left), str(bottom), str(right), str(top)]) url = "http://overpass-api.de/api/map?bbox={box}".format(box=bbox_str) if GetUrl: return url osm_file = get_file(url, output_osm) return output_osm
def shpext_to_boundary(inShp, outShp, epsg=None): """ Read one feature class extent and create a boundary with that extent The outFile could be a Feature Class or one Raster Dataset """ import os from gasp.oss import get_filename from gasp.to.geom import create_point from gasp.prop.ext import get_extent extent = get_extent(inShp, gisApi='ogr') # Create points of the new boundary based on the extent boundary_points = [ create_point(extent[0], extent[3], api='ogr'), create_point(extent[1], extent[3], api='ogr'), create_point(extent[1], extent[2], api='ogr'), create_point(extent[0], extent[2], api='ogr'), create_point(extent[0], extent[3], api='ogr') ] # Get SRS for the output if not epsg: from gasp.prop.prj import get_shp_sref srs = get_shp_sref(inShp) else: from gasp.prop.prj import get_sref_from_epsg srs = get_sref_from_epsg(epsg) # Write new file shp = ogr.GetDriverByName(drv_name(outShp)).CreateDataSource(outShp) lyr = shp.CreateLayer(get_filename(outShp, forceLower=True), srs, geom_type=ogr.wkbPolygon) outDefn = lyr.GetLayerDefn() feat = ogr.Feature(outDefn) ring = ogr.Geometry(ogr.wkbLinearRing) for pnt in boundary_points: ring.AddPoint(pnt.GetX(), pnt.GetY()) polygon = ogr.Geometry(ogr.wkbPolygon) polygon.AddGeometry(ring) feat.SetGeometry(polygon) lyr.CreateFeature(feat) feat.Destroy() shp.Destroy() return outShp
def create_random_points(area_shp, number, out_random): """ Return a dataset with several random points """ from osgeo import ogr from gasp.prop.ff import drv_name from gasp.prop.ext import get_extent # Get extent left, right, bottom, top = get_extent(area_shp, gisApi='ogr') # To be continued """
def fishnet(output, templateExtent, geomType='POLYGON', numRows=None, numColumns=None, cellWidth=None, cellHeight=None, labeling="NO_LABELS"): """ Create a fishnet - rectangular cells Use fc or raster to assign a extent to the new fishnet """ import os from gasp.prop.ext import rst_ext, get_extent from gasp.prop.ff import vector_formats, raster_formats from gasp.oss import get_fileformat templateFormat = get_fileformat(templateExtent) if templateFormat in vector_formats(): xmin, xmax, ymin, ymax = get_extent(templateExtent, gisApi='arcpy') elif templateFormat in raster_formats(): xmin, xmax, ymin, ymax = rst_ext(templateExtent, gisApi='arcpy') else: raise ValueError(('Could not identify if observerDataset ' 'is a raster or a feature class')) arcpy.CreateFishnet_management( out_feature_class=output, origin_coord=' '.join([str(xmin), str(ymin)]), y_axis_coord=' '.join([str(xmin), str(ymin + 10.0)]), cell_width=cellWidth, cell_height=cellHeight, number_rows=numRows, number_columns=numColumns, labels=labeling, template=templateExtent, geometry_type=geomType) return output
def download_by_boundary(input_boundary, output_osm, epsg, GetUrl=True): """ Download data from OSM using a bounding box """ import os from osgeo import ogr from gasp.web import get_file from gasp.oss import get_fileformat, get_filename if type(input_boundary) == dict: if 'top' in input_boundary and 'bottom' in input_boundary \ and 'left' in input_boundary and 'right' in input_boundary: left, right, bottom, top = (input_boundary['left'], input_boundary['right'], input_boundary['bottom'], input_boundary['top']) else: raise ValueError( ('input_boundary is a dict but the keys are not correct. ' 'Please use left, right, top and bottom as keys')) elif type(input_boundary) == list: if len(input_boundary) == 4: left, right, bottom, top = input_boundary else: raise ValueError( ('input boundary is a list with more than 4 objects. ' 'The list should be like: ' 'l = [left, right, bottom, top]')) elif type(input_boundary) == ogr.Geometry: # Check if we have a polygon geom_name = input_boundary.GetGeometryName() if geom_name == 'POLYGON' or geom_name == 'MULTIPOLYGON': # Get polygon extent left, right, bottom, top = input_boundary.GetEnvelope() else: raise ValueError(('Your boundary is a non POLYGON ogr Geometry ')) else: # Assuming input boundary is a file #Check if file exists if not os.path.exists(input_boundary): raise ValueError( ("Sorry, but the file {} does not exist inside the folder {}!" ).format(os.path.basename(input_boundary), os.path.dirname(input_boundary))) # Check if is a raster from gasp.prop.ff import check_isRaster isRst = check_isRaster(input_boundary) if isRst: from gasp.prop.ext import rst_ext # Get raster extent left, right, bottom, top = rst_ext(input_boundary) else: from gasp.prop.feat import feat_count from gasp.prop.ext import get_extent # Check number of features number_feat = feat_count(input_boundary, gisApi='ogr') if number_feat != 1: raise ValueError( ('Your boundary has more than one feature. ' 'Only feature classes with one feature are allowed.')) # Get boundary extent left, right, bottom, top = get_extent(input_boundary, gisApi='ogr') if epsg != 4326: from gasp.to.geom import create_point from gasp.mng.prj import project_geom bottom_left = project_geom(create_point(left, bottom, api='ogr'), epsg, 4326, api='ogr') top_right = project_geom(create_point(right, top, api='ogr'), epsg, 4326, api='ogr') left, bottom = bottom_left.GetX(), bottom_left.GetY() right, top = top_right.GetX(), top_right.GetY() bbox_str = ','.join([str(left), str(bottom), str(right), str(top)]) url = "https://overpass-api.de/api/map?bbox={box}".format(box=bbox_str) if GetUrl: return url if get_fileformat(output_osm) != '.xml': output_osm = os.path.join(os.path.dirname(output_osm), get_filename(output_osm) + '.xml') osm_file = get_file(url, output_osm) return output_osm
def service_area_as_sup_cst(networkDataset, rdvName, extentLyr, originsLyr, output, epsg=3763, REF_DISTANCE=3000, NR_INTERVALS=20): """ Create a Cost Distance Surface using Service Area Tool Same result of the Cost Distance tool but using Service Area Tool Supported by Google Maps API PROBLEM: REF_DISTANCE should be greater if the extent is higher. """ import os from gasp.prop.ext import get_extent from gasp.cpu.arcg.lyr import feat_lyr from gasp.to.shp.arcg import geomArray_to_fc from gasp.mob.arctbx.svarea import service_area_polygon from gasp.web.glg.distmatrix import get_max_dist if epsg != 4326: from gasp.mng.prj import project arcpy.env.overwriteOutput = True # Get extent minX, maxX, minY, maxY = get_extent(extentLyr, gisApi='arcpy') # Get Reference points through the boundary # Get North West to East north_west_east = [(minX, maxY)] # Get South West to East south_west_east = [(minX, minY)] c = minX while c < maxX: north_west_east.append((c, maxY)) south_west_east.append((c, minY)) c += REF_DISTANCE north_west_east.append((maxX, maxY)) south_west_east.append((maxX, minY)) # Get West North to South west_north_to_south = [(minX, maxY)] # Get East North to South east_north_to_south = [(maxX, maxY)] c = maxY while c > minY: west_north_to_south.append((minX, c)) east_north_to_south.append((maxX, c)) c -= REF_DISTANCE west_north_to_south.append((minX, minY)) east_north_to_south.append((maxX, minY)) south_west_east.reverse() west_north_to_south.reverse() # Export Ref Points to a file only to see the result REF_GEOM = north_west_east + east_north_to_south + \ south_west_east + west_north_to_south line_array = [{'FID': 0, "GEOM": REF_GEOM}] REF_POINTS = os.path.join(os.path.dirname(output), 'extent.shp') geomArray_to_fc(line_array, REF_POINTS, "POLYLINE", epsg, overwrite=True) # Calculate time-distance between origins Lyr and reference points # Get Geom of originsLyr # Convert to WGS84 if epsg != 4326: originsWGS = project( originsLyr, os.path.join(os.path.dirname(output), 'origins_wgs84.shp'), 4326) else: originsWGS = originsLyr origLyr = feat_lyr(originsWGS) origPoint = [] for line in arcpy.SearchCursor(origLyr): pnt = line.Shape.centroid origPoint.append((pnt.X, pnt.Y)) # Get WGS REF POINTS if epsg != 4326: refWGS = project( REF_POINTS, os.path.join(os.path.dirname(output), 'extent_wgs.shp'), 4326) else: refWGS = REF_POINTS refPointsLyr = feat_lyr(refWGS) refPoints = [] for line in arcpy.SearchCursor(refPointsLyr): geom = line.getValue("Shape") for vector in geom: for pnt in vector: pnt_str = str(pnt).split(' ') refPoints.append((pnt_str[0], pnt_str[1])) # From that distances, get time intervals max_distance = get_max_dist(origPoint, refPoints) INTERVAL_RANGE = int(round(max_distance / NR_INTERVALS, 0)) c = 0 INTERVALS = [] for i in range(NR_INTERVALS): INTERVALS.append(c + INTERVAL_RANGE) c += INTERVAL_RANGE # Run Service Area Tool service_area_polygon(networkDataset, rdvName, INTERVALS, originsLyr, output) return output
def service_area_as_sup_cst2(networkDataset, rdvName, extentLyr, originsLyr, output, epsg, REF_DISTANCE=3000, NR_INTERVALS=20): """ Create a Cost Distance Surface using Service Area Tool Same result of the Cost Distance tool but using Service Area Tool Support by ArcGIS Closest Facility tool """ import os from gasp.prop.ext import get_extent from gasp.cpu.arcg.mng.feat import vertex_to_point from gasp.cpu.arcg.mng.fld import field_statistics from gasp.cpu.arcg.geometry import geomArray_to_polyline_gon from gasp.mob.arctbx.closest import closest_facility from gasp.mob.arctbx.svarea import service_area_polygon arcpy.env.overwriteOutput = True # Get extent minX, maxX, minY, maxY = get_extent(extentLyr, gisApi='arcpy') # Get Reference points through the boundary # Get North West to East north_west_east = [(minX, maxY)] # Get South West to East south_west_east = [(minX, minY)] c = minX while c < maxX: north_west_east.append((c, maxY)) south_west_east.append((c, minY)) c += REF_DISTANCE north_west_east.append((maxX, maxY)) south_west_east.append((maxX, minY)) # Get West North to South west_north_to_south = [(minX, maxY)] # Get East North to South east_north_to_south = [(maxX, maxY)] c = maxY while c > minY: west_north_to_south.append((minX, c)) east_north_to_south.append((maxX, c)) c -= REF_DISTANCE west_north_to_south.append((minX, minY)) east_north_to_south.append((maxX, minY)) south_west_east.reverse() west_north_to_south.reverse() # Export Ref Points to a file only to see the result REF_GEOM = north_west_east + east_north_to_south + \ south_west_east + west_north_to_south line_array = [{'FID': 0, "GEOM": REF_GEOM}] REF_LINE = os.path.join(os.path.dirname(output), 'extent.shp') geomArray_to_polyline_gon(line_array, REF_LINE, "POLYLINE", epsg, overwrite=True) # Ref Line to Ref Points REF_POINTS = vertex_to_point( REF_LINE, os.path.join(os.path.dirname(output), 'extent_pnt.shp')) REF_TABLE = os.path.join(os.path.dirname(output), 'time_ref_table.dbf') closest_facility(networkDataset, rdvName, originsLyr, REF_POINTS, REF_TABLE, oneway_restriction=True) # Get Maximum Time Registed MAX_DIST = field_statistics(REF_TABLE, 'Total_Minu', 'MAX')[0] INTERVAL_RANGE = int(round(MAX_DIST / NR_INTERVALS, 0)) c = 0 INTERVALS = [] for i in range(NR_INTERVALS): INTERVALS.append(c + INTERVAL_RANGE) c += INTERVAL_RANGE # Run Service Area Tool service_area_polygon(networkDataset, rdvName, INTERVALS, originsLyr, output) return output
def create_fishnet(boundary, fishnet, width=None, height=None, rowN=None, colN=None): """ Create a Fishnet """ import os from math import ceil from gasp.oss import get_filename from gasp.prop.ff import drv_name from gasp.prop.ext import get_extent from gasp.prop.prj import get_shp_sref # Get boundary extent xmin, xmax, ymin, ymax = [float(x) for x in get_extent(boundary, gisApi='ogr')] if width and height: # Clean width and height if type(width) != float: try: # Convert to float width = float(width) except: raise ValueError( 'Width value is not valid. Please give a numeric value' ) if type(height) != float: try: # Convert to float height = float(height) except: raise ValueError( 'Height value is not valid. Please give a numeric value' ) # get rows number rows = ceil((ymax-ymin) / height) # get columns number cols = ceil((xmax-xmin) / width) else: if rowN and colN: rows = int(rowN); cols = int(colN) width = ceil((xmax-xmin) / rows) height = ceil((ymax-ymin) / cols) else: raise ValueError( "You must specify the width and height of fishnet cells or " "instead the number of rows and cols of fishnet" ) # Create output file if not os.path.exists(os.path.dirname(fishnet)): raise ValueError('The path for the output doesn\'t exist') out_fishnet = ogr.GetDriverByName(drv_name( fishnet)).CreateDataSource(fishnet) fishnet_lyr = out_fishnet.CreateLayer( str(get_filename(fishnet)), srs=get_shp_sref(boundary), geom_type=ogr.wkbPolygon ) feat_defn = fishnet_lyr.GetLayerDefn() # create grid cells # - start grid cell envelope -# ringXleftOrigin = xmin ringXrightOrigin = xmin + width ringYtopOrigin = ymax ringYbottomOrigin = ymax - height count_cols = 0 while count_cols < cols: count_cols += 1 # reset envelope for rows ringYtop = ringYtopOrigin ringYbottom = ringYbottomOrigin count_rows = 0 while count_rows < rows: count_rows += 1 ring = ogr.Geometry(ogr.wkbLinearRing) ring.AddPoint(ringXleftOrigin, ringYtop) ring.AddPoint(ringXrightOrigin, ringYtop) ring.AddPoint(ringXrightOrigin, ringYbottom) ring.AddPoint(ringXleftOrigin, ringYbottom) ring.AddPoint(ringXleftOrigin, ringYtop) poly = ogr.Geometry(ogr.wkbPolygon) poly.AddGeometry(ring) # add new geom to layer out_feature = ogr.Feature(feat_defn) out_feature.SetGeometry(poly) fishnet_lyr.CreateFeature(out_feature) out_feature = None # new envelope for next poly ringYtop = ringYtop - height ringYbottom = ringYbottom - height # new envelope for next poly ringXleftOrigin = ringXleftOrigin + width ringXrightOrigin = ringXrightOrigin + width out_fishnet.Destroy() return fishnet
def points_as_grid(boundary, fishnet_pnt, width=None, height=None, nr_cols=None, nr_rows=None): """ Equivalent to the centroid of each cell of a fishnet grid """ import os from math import ceil from gasp.oss import get_filename from gasp.prop.ff import drv_name from gasp.prop.ext import get_extent from gasp.prop.prj import get_shp_sref # Get boundary extent xmin, xmax, ymin, ymax = get_extent(boundary, gisApi='ogr') # Clean width and height if width and height: if type(width) != float: try: # Convert to float width = float(width) except: raise ValueError( 'Width value is not valid. Please give a numeric value' ) if type(height) != float: try: # Convert to float height = float(height) except: raise ValueError( 'Height value is not valid. Please give a numeric value' ) else: if nr_cols and nr_rows: if type(nr_cols) != float: try: # convert to float nr_cols = float(nr_cols) except: raise ValueError( 'Columns number value is not valid. Please give a numeric value' ) if type(nr_rows) != float: try: nr_rows = float(nr_rows) except: raise ValueError( 'Lines number value is not valid. Please give a numeric value' ) width = (xmax + xmin) / nr_cols height = (ymax + ymin) / nr_rows else: raise ValueError('Please giver numeric values to with/height or to nr_cols/nr_rows') # get rows number rows = ceil((ymax-ymin) / height) # get columns number cols = ceil((xmax-xmin) / width) # Create output file if not os.path.exists(os.path.dirname(fishnet_pnt)): return 'The path for the output doesn\'t exist' out_fishnet = ogr.GetDriverByName(drv_name( fishnet_pnt)).CreateDataSource(fishnet_pnt) fishnet_lyr = out_fishnet.CreateLayer( get_filename(fishnet_pnt), get_shp_sref(boundary), geom_type=ogr.wkbPoint ) feat_defn = fishnet_lyr.GetLayerDefn() # create grid cells # - start grid cell envelope -# ringXleftOrigin = xmin ringXrightOrigin = xmin + width ringYtopOrigin = ymax ringYbottomOrigin = ymax - height count_cols = 0 while count_cols < cols: count_cols += 1 # reset envelope for rows ringYtop = ringYtopOrigin ringYbottom = ringYbottomOrigin count_rows = 0 while count_rows < rows: count_rows += 1 pnt = ogr.Geometry(ogr.wkbPoint) pnt.AddPoint( (ringXleftOrigin + ringXrightOrigin) / 2.0, (ringYbottom + ringYtop) / 2.0 ) # add new geom to layer out_feature = ogr.Feature(feat_defn) out_feature.SetGeometry(pnt) fishnet_lyr.CreateFeature(out_feature) out_feature = None # new envelope for next poly ringYtop = ringYtop - height ringYbottom = ringYbottom - height # new envelope for next poly ringXleftOrigin = ringXleftOrigin + width ringXrightOrigin = ringXrightOrigin + width out_fishnet.Destroy()
def shpext_to_rst(inShp, outRaster, cellsize=None, epsg=None, invalidResultAsNone=None, outEpsg=None): """ Extent to raster if invalidResultAsNone - if for some reason something went wrong, the result of this method will be a None Object if there is an error on the numpy array creation. If False, an error will be raised. """ import os import numpy from osgeo import gdal from gasp.prop.ff import drv_name from gasp.prop.ext import get_extent cellsize = 10 if not cellsize else cellsize # Get extent try: left, right, bottom, top = get_extent(inShp, gisApi='ogr') except: left, right, bottom, top = inShp.GetEnvelope() if outEpsg and epsg and outEpsg != epsg: from gasp.to.geom import create_polygon, create_point from gasp.mng.prj import project_geom extGeom = project_geom(create_polygon([ create_point(left, top, api='ogr'), create_point(right, top, api='ogr'), create_point(right, bottom, api='ogr'), create_point(left, bottom, api='ogr'), create_point(left, top, api='ogr') ]), epsg, outEpsg, api='ogr') left, right, bottom, top = extGeom.GetEnvelope() # Get row and cols number rows = (float(top) - float(bottom)) / cellsize cols = (float(right) - float(left)) / cellsize rows = int(rows) if rows == int(rows) else int(rows) + 1 cols = int(cols) if cols == int(cols) else int(cols) + 1 if not invalidResultAsNone: NEW_RASTER_ARRAY = numpy.zeros((rows, cols)) else: try: NEW_RASTER_ARRAY = numpy.zeros((rows, cols)) except: return None # Create new raster img = gdal.GetDriverByName(drv_name(outRaster)).Create( outRaster, cols, rows, 1, #gdal.GDT_Int16 gdal.GDT_Byte) img.SetGeoTransform((left, cellsize, 0, top, 0, -cellsize)) band = img.GetRasterBand(1) band.WriteArray(NEW_RASTER_ARRAY) if epsg: from osgeo import osr rstSrs = osr.SpatialReference() rstSrs.ImportFromEPSG(epsg) img.SetProjection(rstSrs.ExportToWkt()) band.FlushCache() return outRaster