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.feat 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 shpextent_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.feat 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 shp_to_raster(shp, inSource, cellsize, nodata, outRaster, epsg=None, rst_template=None, api='gdal', snap=None): """ Feature Class to Raster cellsize will be ignored if rst_template is defined * API's Available: - gdal; - arcpy; - pygrass; - grass; """ if api == 'gdal': from osgeo import gdal, ogr from gasp.prop.ff import drv_name if not epsg: from gasp.prop.feat import get_shp_sref srs = get_shp_sref(shp).ExportToWkt() else: from gasp.prop.prj import epsg_to_wkt srs = epsg_to_wkt(epsg) # Get Extent dtShp = ogr.GetDriverByName(drv_name(shp)).Open(shp, 0) lyr = dtShp.GetLayer() if not rst_template: x_min, x_max, y_min, y_max = lyr.GetExtent() x_res = int((x_max - x_min) / cellsize) y_res = int((y_max - y_min) / cellsize) else: from gasp.fm.rst import rst_to_array img_temp = gdal.Open(rst_template) geo_transform = img_temp.GetGeoTransform() y_res, x_res = rst_to_array(rst_template).shape # Create output dtRst = gdal.GetDriverByName(drv_name(outRaster)).Create( outRaster, x_res, y_res, gdal.GDT_Byte) if not rst_template: dtRst.SetGeoTransform((x_min, cellsize, 0, y_max, 0, -cellsize)) else: dtRst.SetGeoTransform(geo_transform) dtRst.SetProjection(srs) bnd = dtRst.GetRasterBand(1) bnd.SetNoDataValue(nodata) gdal.RasterizeLayer(dtRst, [1], lyr, burn_values=[1]) del lyr dtShp.Destroy() elif api == 'arcpy': import arcpy if rst_template: tempEnvironment0 = arcpy.env.extent arcpy.env.extent = template if snap: tempSnap = arcpy.env.snapRaster arcpy.env.snapRaster = snap obj_describe = arcpy.Describe(shp) geom = obj_describe.ShapeType if geom == u'Polygon': arcpy.PolygonToRaster_conversion(shp, inField, outRaster, "CELL_CENTER", "NONE", cellsize) elif geom == u'Polyline': arcpy.PolylineToRaster_conversion(shp, inField, outRaster, "MAXIMUM_LENGTH", "NONE", cellsize) if rst_template: arcpy.env.extent = tempEnvironment0 if snap: arcpy.env.snapRaster = tempSnap elif api == 'grass' or api == 'pygrass': """ Vectorial geometry to raster If source is None, the convertion will be based on the cat field. If source is a string, the convertion will be based on the field with a name equal to the given string. If source is a numeric value, all cells of the output raster will have that same value. """ __USE = "cat" if not inSource else "attr" if type(inSource) == str or \ type(inSource) == unicode else "val" if type(inSource) == int or \ type(inSource) == float else None if not __USE: raise ValueError('\'source\' parameter value is not valid') if api == 'pygrass': from grass.pygrass.modules import Module m = Module("v.to.rast", input=shp, output=outRaster, use=__USE, attribute_column=inSource if __USE == "attr" else None, value=inSource if __USE == "val" else None, overwrite=True, run_=False, quiet=True) m() else: from gasp import exec_cmd rcmd = exec_cmd(( "v.to.rast input={} output={} use={}{} " "--overwrite --quiet" ).format( shp, outRaster, __USE, "" if __USE == "cat" else " attribute_column={}".format(inSource) \ if __USE == "attr" else " val={}".format(inSource) )) else: raise ValueError('API {} is not available'.format(api)) return outRaster
def polylines_from_points(points, polylines, POLYLINE_COLUMN, ORDER_FIELD=None, epsg=None): """ Create a Polyline Table from a Point Table A given Point Table: FID | POLYLINE_ID | ORDER_FIELD 0 | P1 | 1 1 | P1 | 2 2 | P1 | 3 3 | P1 | 4 4 | P2 | 1 5 | P2 | 2 6 | P2 | 3 7 | P2 | 4 Will be converted into a new Polyline Table: FID | POLYLINE_ID 0 | P1 1 | P2 In the Point Table, the POLYLINE_ID field identifies the Polyline of that point, the ORDER FIELD specifies the position (first point, second point, etc.) of the point in the polyline. If no ORDER field is specified, the points will be assigned to polylines by reading order. """ import os from osgeo import ogr from gasp.prop.ff import drv_name from gasp.mng.prj import ogr_def_proj from gasp.mng.fld import ogr_list_fields_defn from gasp.mng.fld import add_fields # TODO: check if geometry is correct # List all points pntSrc = ogr.GetDriverByName(drv_name(points)).Open(points) pntLyr = pntSrc.GetLayer() lPnt = {} cnt = 0 for feat in pntLyr: # Get Point Geom geom = feat.GetGeometryRef() # Polyline identification polyline = feat.GetField(POLYLINE_COLUMN) # Get position in the polyline order = feat.GetField(ORDER_FIELD) if ORDER_FIELD else cnt # Store data if polyline not in lPnt.keys(): lPnt[polyline] = {order: (geom.GetX(), geom.GetY())} else: lPnt[polyline][order] = (geom.GetX(), geom.GetY()) cnt += 1 # Write output lineSrc = ogr.GetDriverByName( drv_name(polylines)).CreateDataSource(polylines) if not epsg: from gasp.prop.feat import get_shp_sref srs = get_shp_sref(points) else: from gasp.prop.prj import get_sref_from_epsg srs = get_sref_from_epsg(epsg) lineLyr = lineSrc.CreateLayer(os.path.splitext( os.path.basename(polylines))[0], srs, geom_type=ogr.wkbLineString) # Create polyline id field fields_types = ogr_list_fields_defn(pntLyr) add_fields(lineLyr, {POLYLINE_COLUMN: fields_types[POLYLINE_COLUMN].keys()[0]}) polLnhDefns = lineLyr.GetLayerDefn() # Write lines for polyline in lPnt: new_feature = ogr.Feature(polLnhDefns) lnh = ogr.Geometry(ogr.wkbLineString) pnt_order = lPnt[polyline].keys() pnt_order.sort() for p in pnt_order: lnh.AddPoint(lPnt[polyline][p][0], lPnt[polyline][p][1]) new_feature.SetField(POLYLINE_COLUMN, polyline) new_feature.SetGeometry(lnh) lineLyr.CreateFeature(new_feature) new_feature = None pntSrc.Destroy() lineSrc.Destroy() return polylines
def polyline_to_points(inShp, outShp, attr=None, epsg=None): """ Polyline vertex to Points TODO: See if works with Polygons """ import os from osgeo import ogr from gasp.prop.ff import drv_name from gasp.mng.fld import ogr_copy_fields # Open Input polyData = ogr.GetDriverByName(drv_name(inShp)).Open(inShp) polyLyr = polyData.GetLayer() # Get SRS for the output if not epsg: from gasp.prop.feat 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(outShp)).CreateDataSource(outShp) pntLyr = pntData.CreateLayer(os.path.splitext(os.path.basename(outShp))[0], srs, geom_type=ogr.wkbPoint) # Copy fields from input to output if attr: if attr == 'ALL': attr = None else: attr = [attr] if type(attr) != list else attr ogr_copy_fields(polyLyr, pntLyr, __filter=attr) # Polyline Vertex to Point Feature Class pntLyrDefn = pntLyr.GetLayerDefn() for feat in polyLyr: geom = feat.GetGeometryRef() # Get point count nrPnt = geom.GetPointCount() # Add point to a new feature for p in range(nrPnt): x, y, z = geom.GetPoint(p) new_point = ogr.Geometry(ogr.wkbPoint) new_point.AddPoint(x, y) new_feature = ogr.Feature(pntLyrDefn) new_feature.SetGeometry(new_point) if attr: for at in attr: new_feature.SetField(at, feat.GetField(at)) pntLyr.CreateFeature(new_feature) new_feature.Destroy() del pntLyr del polyLyr pntData.Destroy() polyData.Destroy() return outShp
def eachfeat_to_newshp(inShp, outFolder, epsg=None): """ Export each feature in inShp to a new/single File """ import os from osgeo import ogr from gasp.prop.ff import drv_name from gasp.prop.feat import get_geom_type from gasp.mng.fld import lst_fld from gasp.mng.fld import ogr_copy_fields from gasp.oss import get_fileformat, get_filename inDt = ogr.GetDriverByName(drv_name(inShp)).Open(inShp) lyr = inDt.GetLayer() # Get SRS for the output if not epsg: from gasp.prop.feat import get_shp_sref srs = get_shp_sref(lyr) else: from gasp.prop.prj import get_sref_from_epsg srs = get_sref_from_epsg(epsg) # Get fields name fields = lst_fld(lyr) # Get Geometry type geomCls = get_geom_type(inShp, gisApi='ogr', name=None, py_cls=True) # Read features and create a new file for each feature RESULT_SHP = [] for feat in lyr: # Create output newShp = os.path.join( outFolder, "{}_{}{}".format(get_filename(inShp), str(feat.GetFID()), get_fileformat(inShp))) newData = ogr.GetDriverByName( drv_name(newShp)).CreateDataSource(newShp) newLyr = newData.CreateLayer(str(get_filename(newShp)), srs, geom_type=geomCls) # Copy fields from input to output ogr_copy_fields(lyr, newLyr) newLyrDefn = newLyr.GetLayerDefn() # Create new feature newFeat = ogr.Feature(newLyrDefn) # Copy geometry geom = feat.GetGeometryRef() newFeat.SetGeometry(geom) # Set fields attributes for fld in fields: newFeat.SetField(fld, feat.GetField(fld)) # Save feature newLyr.CreateFeature(newFeat) newFeat.Destroy() del newLyr newData.Destroy() RESULT_SHP.append(newShp) return RESULT_SHP
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.feat 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.feat 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 points_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.feat 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