def feat_to_pnt(inShp, outPnt, epsg=None): """ Get Centroid from each line in a PolyLine Feature Class """ import os from osgeo import ogr from gasp.prop.ff import drv_name from gasp.mng.fld import ogr_copy_fields from gasp.mng.fld import lst_fld # TODO: check if geometry is correct # Open data polyData = ogr.GetDriverByName(drv_name(outPnt)).Open(inShp) polyLyr = polyData.GetLayer() # Get SRS for the output if not epsg: from gasp.prop.prj import get_shp_sref srs = get_shp_sref(polyLyr) else: from gasp.prop.prj import get_sref_from_epsg srs = get_sref_from_epsg(epsg) # Create output pntData = ogr.GetDriverByName(drv_name(outPnt)).CreateDataSource(outPnt) pntLyr = pntData.CreateLayer(os.path.splitext(os.path.basename(outPnt))[0], srs, geom_type=ogr.wkbPoint) # Copy fields from input to output fields = lst_fld(polyLyr) ogr_copy_fields(polyLyr, pntLyr) pntLyrDefn = pntLyr.GetLayerDefn() for feat in polyLyr: geom = feat.GetGeometryRef() pnt = geom.Centroid() new_feat = ogr.Feature(pntLyrDefn) new_feat.SetGeometry(pnt) for fld in fields: new_feat.SetField(fld, feat.GetField(fld)) pntLyr.CreateFeature(new_feat) new_feat.Destroy() del pntLyr del polyLyr pntData.Destroy() polyData.Destroy() return outPnt
def ogr_select_by_location(shp, boundary_filter, filtered_output): """ Filter a shp using the location of a boundary_filter shp For now the boundary must have only one feature Writes the filter on a new shp """ import os from osgeo import ogr from gasp.prop.ff import drv_name from gasp.prop.feat import get_geom_type from gasp.mng.gen import copy_feat from gasp.mng.fld import ogr_copy_fields # Open main data dtSrc = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = dtSrc.GetLayer() # Get filter geom filter_shp = ogr.GetDriverByName(drv_name(boundary_filter)).Open( boundary_filter, 0) filter_lyr = filter_shp.GetLayer() c = 0 for f in filter_lyr: if c: break geom = f.GetGeometryRef() c += 1 filter_shp.Destroy() # Apply filter lyr.SetSpatialFilter(geom) # Copy filter objects to a new shape out = ogr.GetDriverByName( drv_name(filtered_output)).CreateDataSource(filtered_output) outLyr = out.CreateLayer(os.path.splitext( os.path.basename(filtered_output))[0], geom_type=get_geom_type(shp, gisApi='ogr', name=None, py_cls=True)) # Copy fields ogr_copy_fields(lyr, outLyr) copy_feat(lyr, outLyr, outDefn=outLyr.GetLayerDefn(), only_geom=False, gisApi='ogrlyr')
def get_shp_sref(shp): """ Get Spatial Reference Object from Feature Class/Lyr """ from osgeo import ogr from gasp.prop.ff import drv_name if type(shp) == ogr.Layer: lyr = shp c = 0 else: data = ogr.GetDriverByName(drv_name(shp)).Open(shp) lyr = data.GetLayer() c = 1 spref = lyr.GetSpatialRef() if c: del lyr data.Destroy() return spref
def dist_to_nodes(pnt_shp, cstSurface, string, w): nodes = ogr.GetDriverByName(drv_name(pnt_shp)).Open(pnt_shp, 0) nodesLyr = nodes.GetLayer() c = 0 dicNodes = {} for pnt in nodesLyr: geom = pnt.GetGeometryRef() point = geom.ExportToWkb() OGR_CreateNewShape( OGR_GetDriverName(pnt_shp), os.path.join(w, '{pnt}_{o}.shp'.format(pnt=string, o=str(c))), ogr.wkbPoint, [point]) FT_TF_GRASS( os.path.join(w, '{pnt}_{o}.shp'.format(pnt=string, o=str(c))), '{pnt}_{o}'.format(pnt=string, o=str(c)), 'None') GRASS_CostDistance(cstSurface, '{pnt}_{o}'.format(pnt=string, o=str(c)), 'cst_{pnt}_{a}'.format(pnt=string, a=str(c))) dicNodes['{pnt}_{o}'.format(pnt=string, o=str(c))] = [ os.path.join(w, '{pnt}_{o}.shp'.format(pnt=string, o=str(c))), 'cst_{pnt}_{a}'.format(pnt=string, a=str(c)) ] c += 1 return dicNodes
def add_fields(table, fields): """ Receive a feature class and a dict with the field name and type and add the fields in the feature class TODO: Check if fields is a dict """ import os if type(table) == ogr.Layer: lyr = table c = 0 else: if os.path.exists(table) and os.path.isfile(table): # Open table in edition mode __table = ogr.GetDriverByName(drv_name(table)).Open(table, 1) # Get Layer lyr = __table.GetLayer() c = 1 else: raise ValueError('File path does not exist') for fld in fields: lyr.CreateField(ogr.FieldDefn(fld, fields[fld])) if c: del lyr __table.Destroy() else: return lyr
def get_centroid_boundary(shp, isFile=None): """ Return centroid (OGR Point object) of a Boundary (layer with a single feature). """ from osgeo import ogr from gasp.prop.ff import drv_name if isFile: shp = ogr.GetDriverByName( drv_name(shp)).Open(shp, 0) lyr = shp.GetLayer() feat = lyr[0]; geom = feat.GetGeometryRef() else: geom = shp centroid = geom.Centroid() cnt = ogr.CreateGeometryFromWkt(centroid.ExportToWkt()) shp.Destroy() return cnt
def lst_fld(shp): """ Return a list with every field name in a vectorial layer """ if type(shp) == ogr.Layer: lyr = shp c = 0 else: data = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = data.GetLayer() c = 1 defn = lyr.GetLayerDefn() fields = [] for i in range(0, defn.GetFieldCount()): fdefn = defn.GetFieldDefn(i) fields.append(fdefn.name) if c: del lyr data.Destroy() return fields
def rst_val_to_points(pnt, rst): """ Extract, for a given point dataset, the value of a cell with the same location Returns a dict: d = { fid: value, ... } """ from osgeo import ogr from gasp.prop.ff import drv_name values_by_point = {} shp = ogr.GetDriverByName(drv_name(pnt)).Open(pnt, 0) lyr = shp.GetLayer() img = gdal.Open(rst) geo_transform = img.GetGeoTransform() band = img.GetRasterBand(1) for feat in lyr: geom = feat.GetGeometryRef() mx, my = geom.GetX(), geom.GetY() px = int((mx - geo_transform[0]) / geo_transform[1]) py = int((my - geo_transform[3]) / geo_transform[5]) val_pix = band.ReadAsArray(px, py, 1, 1) values_by_point[int(feat.GetFID())] = float(val_pix[0][0]) return values_by_point
def get_geom_by_index(inShp, idx): """ Get Geometry by index in file """ from osgeo import ogr from gasp.prop.ff import drv_name src = ogr.GetDriverByName(drv_name(inShp)).Open(inShp) lyr = src.GetLayer() c = 0 geom = None for f in lyr: if idx == c: geom = f.GetGeometryRef() else: c += 1 if not geom: raise ValueError("inShp has not idx") _geom = geom.ExportToWkt() del lyr src.Destroy() return _geom
def ogr_list_fields_defn(shp): """ Return a dict with the field name as key and the field definition as value Field defn is the same of saying name + type """ if type(shp) == ogr.Layer: lyr = shp c = 0 else: data = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = data.GetLayer() c = 1 defn = lyr.GetLayerDefn() fields = {} for i in range(0, defn.GetFieldCount()): fdefn = defn.GetFieldDefn(i) fieldType = fdefn.GetFieldTypeName(fdefn.GetType()) fields[fdefn.name] = {fdefn.GetType(): fieldType} if c: del lyr data.Destroy() return fields
def area_to_dic(shp): """ Return the following output: dic = { id_feat: area, ..., id_feat: area } """ from osgeo import ogr from gasp.prop.ff import drv_name o = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) l = o.GetLayer() d = {} c = 0 for feat in l: g = feat.GetGeometryRef() area = g.GetArea() d[c] = area c += 1 del l o.Destroy() return d
def sel_by_attr(inShp, sql, outShp, geomType="area", lyrN=1, api_gis='ogr'): """ Select vectorial file and export to new file If api_gis == 'grass' or 'pygrass', sql is not a query but the where clause API's Available: * ogr; * grass; * pygrass """ if api_gis == 'ogr': from gasp import exec_cmd from gasp.prop.ff import drv_name out_driver = drv_name(outShp) cmd = 'ogr2ogr -f "{drv}" {o} {i} -dialect sqlite -sql "{s}"'.format( o=outShp, i=inShp, s=sql, drv=out_driver) # Execute command outcmd = exec_cmd(cmd) elif api_gis == 'pygrass': """ v.extract via pygrass """ from grass.pygrass.modules import Module m = Module("v.extract", input=inShp, type=geomType, layer=lyrN, where=sql, output=outShp, overwrite=True, run_=False, quiet=True) m() elif api_gis == 'grass': """ v.extract via command shell """ from gasp import exec_cmd rcmd = exec_cmd( ("v.extract input={} type={} layer={} where={} " "output={} --overwrite --quiet").format(inShp, geomType, str(lyrN), sql, outShp)) else: raise ValueError('API {} is not available'.format(api_gis)) return outShp
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 array_to_raster(inArray, outRst, template, epsg, data_type, noData=None, gisApi='gdal'): """ Send Array to Raster API Available: * gdal; * arcpy """ if gisApi == 'gdal': from osgeo import gdal, osr from gasp.prop.ff import drv_name img_template = gdal.Open(template) geo_transform = img_template.GetGeoTransform() rows, cols = inArray.shape driver = gdal.GetDriverByName(drv_name(outRst)) out = driver.Create(outRst, cols, rows, 1, data_type) out.SetGeoTransform(geo_transform) outBand = out.GetRasterBand(1) if noData: outBand.SetNoDataValue(noData) outBand.WriteArray(inArray) if epsg: from gasp.prop.prj import epsg_to_wkt srs = epsg_to_wkt(epsg) out.SetProjection(srs) outBand.FlushCache() elif gisApi == 'arcpy': import arcpy xmin = arcpy.GetRasterProperties_management(template, "LEFT") cellx = arcpy.GetRasterProperties_management(template, "CELLSIZEX") celly = arcpy.GetRasterProperties_management(template, "CELLSIZEY") new_rst = arcpy.NumPyArrayToRaster(array, float(str(xmin).replace(',', '.')), float(str(cellx).replace(",", ".")), float(str(celly).replace(",", "."))) new_rst.save(outRst) else: raise ValueError('The api {} is not available'.format(gisApi)) return outRst
def get_attr_values_by_location(inShp, attr, geomFilter=None, shpFilter=None): """ Get attributes of the features of inShp that intersects with geomFilter or shpFilter """ from osgeo import ogr from gasp.prop.ff import drv_name if not geomFilter and not shpFilter: raise ValueError( 'A geom object or a path to a sho file should be given') if shpFilter: # For now the shpFilter must have only one feature filter_shp = ogr.GetDriverByName(drv_name(shpFilter)).Open( shpFilter, 0) filter_lyr = filter_shp.GetLayer() c = 0 for f in filter_lyr: if c: break geom = f.GetGeometryRef() c += 1 filter_shp.Destroy() else: geom = geomFilter # Open Main data dtSrc = ogr.GetDriverByName(drv_name(inShp)).Open(inShp, 0) lyr = dtSrc.GetLayer() lyr.SetSpatialFilter(geom) # Get attribute values ATTRIBUTE_VAL = [feat.GetField(attr) for feat in lyr] dtSrc.Destroy() return ATTRIBUTE_VAL
def statistics_by_line_feat(lines, raster, statistic, new_field): """ Estimates raster statistic per line on a linear feature class statistic = statistic type (e.g. max, min, mean, sum) This method has an important problem - depends on the number of vertex of each features """ from osgeo import ogr, gdal from gasp.prop.ff import drv_name from gasp.cpu.gdl.sampling import gdal_point_value_on_raster # Open feature class shp = ogr.GetDriverByName(drv_name(lines)).Open(lines, 1) lyr = shp.GetLayer() # Create new field lyr.CreateField(ogr.FieldDefn(new_field, ogr.OFTReal)) # Open Raster img = gdal.Open(raster) geo_transform = img.GetGeoTransform() band = img.GetRasterBand(1) # For feature in layer for feat in lyr: rst_values = [] # For point in line lnh = feat.GetGeometryRef() num_pnt = lnh.GetPointCount() for pnt in range(num_pnt): x, y, z = lnh.GetPoint(pnt) cell = gdal_point_value_on_raster(x, y, band, geo_transform) if not cell: continue else: rst_values.append(cell) if len(rst_values): if statistic == 'minimum': value = min(rst_values) elif statistic == 'maximum': value = max(rst_values) elif statistic == 'mean': value = sum(rst_values) / len(rst_values) elif statistic == 'sum': value = sum(rst_values) else: continue feat.SetField(new_field, value) lyr.SetFeature(feat)
def shply_array_to_shp(arrayLike, outfile, geomType, epsg=None, fields=None, crsObj=None): """ Convert a array with Shapely 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, geom: geomObj}, {col_1: value, col_2: value, geom: geomObj}, ] """ import os from gasp.prop.ff import drv_name from gasp.prop.prj import get_sref_from_epsg # Create output file shp = ogr.GetDriverByName(drv_name(outfile)).CreateDataSource(outfile) lyr = shp.CreateLayer( os.path.splitext(os.path.basename(outfile))[0], get_sref_from_epsg(epsg) if epsg else crsObj if crsObj else \ None, geom_type=geomType ) # Create fields of output file # TODO: Automatic mapping of filters types needs further testing if fields: for f in fields: lyr.CreateField(ogr.FieldDefn(f, fields[f])) # Add features defn = lyr.GetLayerDefn() for feat in arrayLike: newFeat = ogr.Feature(defn) newFeat.SetGeometry(ogr.CreateGeometryFromWkb(feat['GEOM'].wkb)) if len(fields): for f in fields: newFeat.SetField(f, feat[f]) lyr.CreateFeature(newFeat) newFeat = None shp.Destroy() return outfile
def composite_bnds(rsts, outRst, epsg=None, gisAPI='gdal'): """ Composite Bands API's Available: * gdal; """ if gisAPI == 'gdal': """ Using GDAL """ from osgeo import gdal from gasp.fm.rst import rst_to_array from gasp.prop.ff import drv_name from gasp.prop.rst import rst_dataType, get_nodata # Get Arrays _as = [rst_to_array(r) for r in rsts] # Get nodata values nds = [get_nodata(r, gisApi='gdal') for r in rsts] # Open template and get some metadata img_temp = gdal.Open(rsts[0]) geo_tran = img_temp.GetGeoTransform() band = img_temp.GetRasterBand(1) dataType = rst_dataType(band) rows, cols = _as[0].shape # Create Output drv = gdal.GetDriverByName(drv_name(outRst)) out = drv.Create(outRst, cols, rows, len(_as), dataType) out.SetGeoTransform(geo_tran) if epsg: from gasp.prop.prj import epsg_to_wkt srs = epsg_to_wkt(epsg) out.SetProjection(srs) # Write all bands for i in range(len(_as)): outBand = out.GetRasterBand(i + 1) outBand.SetNoDataValue(nds[i]) outBand.WriteArray(_as[i]) outBand.FlushCache() else: raise ValueError('The api {} is not available'.format(gisAPI)) return outRst
def shp_to_shp(inShp, outShp, gisApi='ogr', supportForSpatialLite=None): """ Convert a vectorial file to another with other file format API's Available: * ogr; * arcpy; When using gisApi='ogr' - Set supportForSpatialLite to True if outShp is a sqlite db and if you want SpatialLite support for that database. """ import os if gisApi == 'ogr': from gasp import exec_cmd from gasp.prop.ff import drv_name out_driver = drv_name(outShp) if out_driver == 'SQLite' and supportForSpatialLite: splite = ' -dsco "SPATIALITE=YES"' else: splite = '' cmd = 'ogr2ogr -f "{drv}" {out} {_in}{lite}'.format(drv=out_driver, out=outShp, _in=inShp, lite=splite) # Run command cmdout = exec_cmd(cmd) elif gisApi == 'arcpy': """ Feature Class to Feature Class using ArcGIS """ import arcpy arcpy.FeatureClassToFeatureClass_conversion(inShp, os.path.dirname(outShp), os.path.basename(outShp), "", "", "") else: raise ValueError('Sorry, API {} is not available'.format(gisApi)) return outShp
def merge_feat(shps, outShp, api="ogr2ogr"): """ Get all features in several Shapefiles and save them in one file """ if api == "ogr2ogr": from gasp import exec_cmd from gasp.prop.ff import drv_name out_drv = drv_name(outShp) # Create output and copy some features of one layer (first in shps) cmdout = exec_cmd('ogr2ogr -f "{}" {} {}'.format( out_drv, outShp, shps[0] )) # Append remaining layers lcmd = [exec_cmd( 'ogr2ogr -f "{}" -update -append {} {}'.format( out_drv, outShp, shps[i] ) ) for i in range(1, len(shps))] elif api == 'pandas': """ Merge SHP using pandas """ from gasp.fm import tbl_to_obj from gasp.to.shp import df_to_shp if type(shps) != list: raise ValueError('shps should be a list with paths for Feature Classes') dfs = [tbl_to_obj(shp) for shp in shps] result = dfs[0] for df in dfs[1:]: result = result.append(df, ignore_index=True, sort=True) df_to_shp(result, outShp) else: raise ValueError( "{} API is not available" ) return outShp
def osmosis_extract(boundary, osmdata, wepsg, output): """ Extract OSM Data from a xml file with osmosis The extraction is done using the extent of a boundary """ import os from osgeo import ogr from gasp import exec_cmd from gasp.prop.ff import drv_name from gasp.mng.prj import project_geom # Assuming that boundary has only one feature # Get Geometry dtSrc = ogr.GetDriverByName(drv_name(boundary)).Open(boundary) lyr = dtSrc.GetLayer() for feat in lyr: geom = feat.GetGeometryRef() break # Convert boundary to WGS84 -EPSG 4326 geom_wgs = project_geom(geom, int(wepsg), 4326, api='ogr') if int(wepsg) != 4326 else geom # Get boundary extent left, right, bottom, top = geom_wgs.GetEnvelope() # Osmosis shell comand osmExt = os.path.splitext(osmdata)[1] osm_f = 'enableDateParsing=no' if osmExt == '.xml' or osmExt == '.osm' else '' cmd = ('osmosis --read-{_f} {p} file={_in} --bounding-box top={t} left={l}' ' bottom={b} right={r} --write-{outext} file={_out}').format( _f='xml' if osmExt == '.xml' or osmExt == '.osm' else 'pbf', p=osm_f, _in=osmdata, t=str(top), l=str(left), b=str(bottom), r=str(right), _out=output, outext=os.path.splitext(output)[1][1:]) # Execute command outcmd = exec_cmd(cmd) return output
def rst_to_rst(inRst, outRst): """ Convert a raster file to another raster format """ from gasp import exec_cmd from gasp.prop.ff import drv_name outDrv = drv_name(outRst) cmd = 'gdal_translate -of {drv} {_in} {_out}'.format( drv=outDrv, _in=inRst, _out=outRst ) cmdout = exec_cmd(cmd) return outRst
def dic_buffer_array_to_shp(arrayBf, outShp, epsg, fields=None): """ Array with dict with buffer proprieties to Feature Class """ import os from osgeo import ogr from gasp.prop.ff import drv_name from gasp.prop.prj import get_sref_from_epsg # Get SRS for output srs = get_sref_from_epsg(epsg) # Create output DataSource and Layer outData = ogr.GetDriverByName(drv_name(outShp)).CreateDataSource(outShp) lyr = outData.CreateLayer(os.path.splitext(os.path.basename(outShp))[0], srs, geom_type=ogr.wkbPolygon) # Create fields if fields: from gasp.mng.fld import add_fields add_fields(lyr, fields) lyrDefn = lyr.GetLayerDefn() for _buffer in arrayBf: newFeat = ogr.Feature(lyrDefn) geom = coord_to_buffer(_buffer["X"], _buffer["Y"], _buffer["RADIUS"]) newFeat.SetGeometry(geom) for field in fields: if field in _buffer.keys(): newFeat.SetField(field, _buffer[field]) lyr.CreateFeature(newFeat) newFeat.Destroy() del lyrDefn outData.Destroy() return outShp
def feat_count(shp, gisApi='pandas'): """ Count the number of features in a feature class API'S Available: * gdal; * arcpy; * pygrass; * pandas; """ if gisApi == 'ogr': from osgeo import ogr from gasp.prop.ff import drv_name data = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = data.GetLayer() fcnt = int(lyr.GetFeatureCount()) data.Destroy() elif gisApi == 'arcpy': import arcpy fcnt = int(arcpy.GetCount_management(lyr).getOutput(0)) elif gisApi == 'pygrass': from grass.pygrass.vector import VectorTopo open_shp = VectorTopo(shp) open_shp.open(mode='r') fcnt = open_shp.num_primitive_of(geom) elif gisApi == 'pandas': from gasp.fm import tbl_to_obj gdf = tbl_to_obj(shp) fcnt = int(gdf.shape[0]) del gdf else: raise ValueError('The api {} is not available'.format(gisApi)) return fcnt
def clip_rst(raster, clipShp, outRst, nodataValue=None): """ Clip Raster using GDAL WARP """ from gasp import exec_cmd from gasp.prop.ff import drv_name outcmd = exec_cmd(( "gdalwarp {ndata}-cutline {clipshp} -crop_to_cutline " "-of {ext} {inraster} -overwrite {outrst}" ).format( clipshp=clipShp, inraster=raster, outrst=outRst, ext=drv_name(outRst), ndata="-dstnodata {} ".format( str(nodataValue)) if nodataValue else "" )) return outRst
def rst_val_to_points2(pntShp, listRasters): """ Pick raster value for each point in pntShp """ from osgeo import ogr from gasp import goToList from gasp.prop.ff import drv_name listRasters = goToList(listRasters) shp = ogr.GetDriverByName( drv_name(pntShp)).Open(pnt, 0) lyr = shp.GetLayer() pntDict = {} for feat in lyr: geom = feat.GetGeometryRef() x, y = geom.GetX(), geom.GetY() l = [] for rst in listRasters: img = gdal.Open(rst) geo_transform = img.GetGeoTransform() band = img.GetRasterBand(1) px = int((x - geo_transform[0]) / geo_transform[1]) py = int((y - geo_transform[3]) / geo_transform[5]) value = band.ReadAsArray(px, py, 1, 1) l.append(list(value)[0]) del img, geo_transform, band, px, py pntDict[feat.GetFID()] = l shp.Destroy() return pntDict
def get_extent(shp, gisApi='ogr'): """ Return extent of a Vectorial file Return a tuple object with the follow order: (left, right, bottom, top) API'S Available: * ogr; * arcpy; """ if gisApi == 'ogr': from osgeo import ogr from gasp.prop.ff import drv_name from decimal import Decimal dt = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = dt.GetLayer() extent = lyr.GetExtent() dt.Destroy() EXT = [Decimal(x) for x in extent] elif gisApi == 'arcpy': import arcpy descObj = arcpy.Describe(shp) EXT = [ descObj.extent.XMin, descObj.extent.XMax, descObj.extent.YMin, descObj.extent.YMax ] else: raise ValueError('The api {} is not available'.format(gisApi)) return EXT
def get_buffer_radius(bfShp, isFile=None): """ Return the radius of a buffer boundary in meters. The layer must be only one feature """ from osgeo import ogr if isFile: bfshp = ogr.GetDriverByName(drv_name(bfShp)).Open(bfShp, 0) bfLyr = bfShp.GetLayer() feat = bfLyr[0] geom = feat.GetGeometryRef() else: geom = ogr.CreateGeometryFromWkt(bfShp) center = geom.Centroid() c = 0 for pnt in geom: if c == 1: break pnt_aux = pnt c += 1 x_center, y_center = (center.GetX(), center.GetY()) x_aux, y_aux = (pnt_aux.GetX(), pnt_aux.GetY()) dist = ((pnt_aux.GetX() - x_center)**2 + (pnt_aux.GetY() - y_center)**2)**0.5 del center if isFile: bfShp.Destroy() return round(dist, 0)
def coords_to_boundary(topLeft, lowerRight, epsg, outshp): """ Top Left and Lower Right to Boundary """ import os from gasp.oss import get_filename from gasp.prop.prj import get_sref_from_epsg boundary_points = [(topLeft[0], topLeft[1]), (lowerRight[0], topLeft[1]), (lowerRight[0], lowerRight[1]), (topLeft[0], lowerRight[1]), (topLeft[0], topLeft[1])] shp = ogr.GetDriverByName(drv_name(outshp)).CreateDataSource(outshp) lyr = shp.CreateLayer(get_filename(outshp), get_sref_from_epsg(epsg), geom_type=ogr.wkbPolygon) outDefn = lyr.GetLayerDefn() feat = ogr.Feature(outDefn) ring = ogr.Geometry(ogr.wkbLinearRing) for pnt in boundary_points: ring.AddPoint(pnt[0], pnt[1]) polygon = ogr.Geometry(ogr.wkbPolygon) polygon.AddGeometry(ring) feat.SetGeometry(polygon) lyr.CreateFeature(feat) feat.Destroy() shp.Destroy() return outshp
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