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 get_random_point(minX, maxX, minY, maxY): import random from gasp.to.geom import create_point x = minX + (random.random() * (maxX - minX)) y = minY + (random.random() * (maxY - minY)) pnt = create_point(x, y, api='ogr') return pnt
def coord_to_buffer(x, y, radius): from gasp.to.geom import create_point pnt = create_point(x, y, api='ogr') return pnt.Buffer(int(round(float(radius), 0)))
def getBufferParam(inArea, inAreaSRS, outSRS=4326): """ Get Buffer X, Y Center and radius in any SRS (radius in meteres). Check the type of the 'inArea' Object and return the interest values. inArea could be a file, dict, list or tuple """ import os from gasp.to.geom import create_point from gasp.mng.prj import project_geom TYPE = type(inArea) if TYPE == str or TYPE == unicode: # Assuming that inArea is a file # Check if exists if os.path.exists(inArea): if os.path.isfile(inArea): from gasp.anls.exct import get_geom_by_index # Get Geometry object BUFFER_GEOM = get_geom_by_index(inArea, 0) # To outSRS if int(inAreaSRS) != outSRS: BUFFER_GEOM = project_geom( ogr.CreateGeometryFromWkt(BUFFER_GEOM), inAreaSRS, outSRS, api='ogr').ExportToWkt() # Get x_center, y_center and radius xyr = buffer_properties(BUFFER_GEOM, outSRS, isFile=None) x_center, y_center, dist = str(xyr['X']), str(xyr['Y']), str( xyr['R']) else: raise ValueError('The given path exists but it is not a file') else: raise ValueError('The given path doesn\'t exist') elif TYPE == dict: X = 'x' if 'x' in inArea else 'X' if 'X' in inArea else \ 'lng' if 'lng' in inArea else None Y = 'y' if 'x' in inArea else 'Y' if 'Y' in inArea else \ 'lat' if 'lat' in inArea else None R = 'r' if 'r' in inArea else 'R' if 'R' in inArea else \ 'rad' if 'rad' in inArea else 'RADIUS' if 'RADIUS' in inArea \ else 'radius' if 'radius' in inArea else None if not X or not Y or not R: raise ValueError( ('The keys used to identify the buffer properties ' 'are not valid! ' 'Please choose one of the following keys groups: ' 'x, y, r; ' 'X, Y, R; ' 'lat, lng, rad')) else: x_center, y_center, dist = (str(inArea[X]), str(inArea[Y]), str(inArea[R])) if inAreaSRS != outSRS: pnt_wgs = project_geom(create_point(x_center, y_center, api='ogr'), inAreaSRS, outSRS, api='ogr') x_center, y_center = (pnt_wgs.GetX(), pnt_wgs.GetY()) elif TYPE == list or TYPE == tuple: x_center, y_center, dist = inArea if inAreaSRS != outSRS: pnt_wgs = project_geom(create_point(x_center, y_center, api='ogr'), inAreaSRS, outSRS, api='ogr') x_center, y_center = (pnt_wgs.GetX(), pnt_wgs.GetY()) else: raise ValueError( ('Please give a valid path to a shapefile or a tuple, dict or ' 'list with the x, y and radius values')) return x_center, y_center, dist
def ogr_buffer(geom, radius, out_file, srs=None): """ For each geometry in the input, this method create a buffer and store it in a vetorial file Accepts files or lists with geom objects as inputs """ from osgeo import ogr from gasp.mng.prj import ogr_def_proj from gasp.prop.ff import drv_name from gasp.prop.prj import get_sref_from_epsg # Create output buffer_shp = ogr.GetDriverByName( drv_name(out_file)).CreateDataSource(out_file) buffer_lyr = buffer_shp.CreateLayer( os.path.splitext(os.path.basename(out_file))[0], get_sref_from_epsg(srs) if srs else None, geom_type=ogr.wkbPolygon) featDefn = buffer_lyr.GetLayerDefn() if type(geom) == list: for g in geom: feat = ogr.Feature(featDefn) feat.SetGeometry(draw_buffer(g, radius)) buffer_lyr.CreateFeature(feat) feat = None buffer_shp.Destroy() elif type(geom) == dict: if 'x' in geom and 'y' in geom: X = 'x' Y = 'y' elif 'X' in geom and 'Y' in geom: X = 'X' Y = 'Y' else: raise ValueError(('Your geom dict has invalid keys. ' 'Please use one of the following combinations: ' 'x, y; ' 'X, Y')) from gasp.to.geom import create_point feat = ogr.Feature(featDefn) g = create_point(geom[X], geom[Y], api='ogr') feat.SetGeometry(draw_buffer(g, radius)) buffer_lyr.CreateFeature(feat) feat = None buffer_shp.Destroy() if srs: ogr_def_proj(out_file, epsg=srs) elif type(geom) == str or type(geom) == unicode: # Check if the input is a file if os.path.exists(geom): inShp = ogr.GetDriverByName(drv_name(geom)).Open(geom, 0) lyr = inShp.GetLayer() for f in lyr: g = f.GetGeometryRef() feat = ogr.Feature(featDefn) feat.SetGeometry(draw_buffer(g, radius)) buffer_lyr.CreateFeature(feat) feat = None buffer_shp.Destroy() inShp.Destroy() if srs: ogr_def_proj(out_file, epsg=srs) else: ogr_def_proj(out_file, template=geom) else: raise ValueError('The given path does not exist') else: raise ValueError('Your geom input is not valid') return out_file
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 array_to_shp(array_like, outFile, x='x', y='y', epsg=None): """ Convert a array with geometric data into a file with geometry (GML, ESRI Shapefile or others). Example of an array_like object: data = [ {col_1: value, col_2: value, x: value, y: value}, {col_1: value, col_2: value, x: value, y: value}, ] This array must contain a 'x' and 'y' keys (or equivalent). TODO: Now works only for points """ import os from gasp import unicode_to_str from gasp.prop.ff import drv_name from gasp.to.geom import create_point from gasp.prop.prj import get_sref_from_epsg from gasp.mng.fld import map_pyType_fldCode from gasp.oss import get_filename ogr.UseExceptions() # Create output file shp = ogr.GetDriverByName(drv_name(outFile)).CreateDataSource(outFile) lyr = shp.CreateLayer( get_filename(outFile), None if not epsg else get_sref_from_epsg(epsg), geom_type=ogr.wkbPoint, ) # Create fields of output file fields = [] keys_fields = {} for k in array_like[0]: if k != x and k != y: fld_name = k[:9] if type(fld_name) == unicode: fld_name = unicode_to_str(fld_name) if fld_name not in fields: fields.append(fld_name) else: # Get All similar fields in the fields list tmp_fld = [] for i in fields: if i[:8] == fld_name[:8]: tmp_fld.append(i[:8]) c = len(tmp_fld) fld_name = fld_name[:8] + '_{n}'.format(n=str(c)) fields.append(fld_name) # TODO: Automatic mapping of filters types needs further testing #fld_type = map_pyType_fldCode(array_like[0][k]) lyr.CreateField(ogr.FieldDefn(fld_name, ogr.OFTString)) keys_fields[k] = fld_name defn = lyr.GetLayerDefn() for i in range(len(array_like)): feat = ogr.Feature(defn) feat.SetGeometry( create_point(array_like[i][x], array_like[i][y], api='ogr')) for k in array_like[i]: if k != x and k != y: value = array_like[i][k] if type(value) == unicode: value = unicode_to_str(value) if len(value) >= 254: value = value[:253] feat.SetField(keys_fields[k], value) lyr.CreateFeature(feat) feat = None shp.Destroy()
def pnts_to_boundary(pntShp, outBound, distMeters): """ Create a boundary from Point using a tolerance in meters """ from osgeo import ogr from gasp.oss import get_filename from gasp.prop.ff import drv_name from gasp.to.geom import create_point from gasp.prop.prj import get_shp_sref SRS = get_shp_sref(pntShp) shp = ogr.GetDriverByName(drv_name(pntShp)).Open(pntShp) lyr = shp.GetLayer() outShp = ogr.GetDriverByName(drv_name(outBound)).CreateDataSource(outBound) outLyr = outShp.CreateLayer(get_filename(outBound, forceLower=True), SRS, geom_type=ogr.wkbPolygon) outDefn = outLyr.GetLayerDefn() for feat in lyr: __feat = ogr.Feature(outDefn) ring = ogr.Geometry(ogr.wkbLinearRing) geom = feat.GetGeometryRef() X, Y = geom.GetX(), geom.GetY() boundary_points = [ create_point(X - distMeters, Y + distMeters, api='ogr'), # Topleft create_point(X + distMeters, Y + distMeters, api='ogr'), # TopRight create_point(X + distMeters, Y - distMeters, api='ogr'), # Lower Right create_point(X - distMeters, Y - distMeters, api='ogr'), # Lower Left create_point(X - distMeters, Y + distMeters, api='ogr') ] for pnt in boundary_points: ring.AddPoint(pnt.GetX(), pnt.GetY()) polygon = ogr.Geometry(ogr.wkbPolygon) polygon.AddGeometry(ring) __feat.SetGeometry(polygon) outLyr.CreateFeature(__feat) feat.Destroy() __feat = None ring = None polygon = None shp.Destroy() outShp.Destroy() return outBound
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
def geovideos_to_array(search_words, epsg_out=4326, spatial_filter=None, epsg_filter=4326): """ Locate videos on youtube and save these locations to a vectorial file """ import os from gasp.oss.ops import del_files_by_name from gasp.to.geom import create_point from gasp.mng.prj import project_geom from gasp.anls.tplgy import point_in_polygon from gasp.anls.prox.bf import draw_buffer videos = get_video_details_by_keyword(search_words) videos_with_location = [] for video in videos: if video['y'] and video['x']: videos_with_location.append(video) if not len(videos_with_location): # Return nodata return 0 if spatial_filter: from gasp.anls.prox.bf import getBufferParam x_center, y_center, dist = getBufferParam( spatial_filter, epsg_filter) bufferCenter = project_geom( create_point(x_center, y_center, api='ogr'), 4326, 3857, api='ogr' ) bufferGeom = draw_buffer(bufferCenter, dist) filterData = [] for instance in videos_with_location: # Create point WGS_POINT = create_point( float(instance['x']), float(instance['y']), api='ogr' ) point = project_geom(WGS_POINT, 4326, 3857, api='ogr') isPointInPolygon = point_in_polygon(point, bufferGeom) if isPointInPolygon: if epsg_out != 4326: trans_point = project_geom(WGS_POINT, 4326, epsg_out, api='ogr') instance['x'] = trans_point.GetX() instance['y'] = trans_point.GetY() filterData.append(instance) return filterData