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 glass.prop.ext import rst_ext, get_extent from glass.prop.ff import vector_formats, raster_formats from glass.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 generate_waterlines(mdt, waterbodies, accumulation_value=500, workspace=None): """ Generate Water Bodies lines """ import os from glass.oss import get_fileformat from glass.cpu.arcg.lyr import rst_lyr from glass.prop.ff import vector_formats, raster_formats from glass.spanlst.algebra import rstcalc from glass.cpu.arcg.spanlst.hydro import fill from glass.cpu.arcg.spanlst.hydro import flow_accumulation from glass.cpu.arcg.spanlst.hydro import flow_direction from glass.cpu.arcg.spanlst.hydro import stream_to_feature workspace = workspace if workspace else \ os.path.dirname(waterbodies) raster_format = os.path.splitext(os.path.basename(waterbodies))[1] arcpy.env.workspace = workspace arcpy.env.overwriteOutput = True fill_rst = fill(mdt, 'flow_raster{}'.format(raster_format), template=mdt) dire_rst = flow_direction( fill_rst, 'direction_raster{}'.format(raster_format), template=mdt ) flow_acc = flow_accumulation( dire_rst, 'flow_raster{}'.format(raster_format), template=mdt ) # Split water bodies from the other accumulation data lyr_flow = rst_lyr(flow_acc) outFormat = os.path.splitext(os.path.basename(waterbodies))[1] rstFormat = raster_formats() vecFormat = vector_formats() waterRst = waterbodies if outFormat in rstFormat else \ os.path.join( workspace, os.path.splitext(os.path.basename(waterbodies))[0] + raster_format ) if outFormat in vecFormat else None if not waterRst: raise ValueError('Your output is not a raster and is not a vector') waterRst = rstcalc( '{r} > {a}'.format( r=os.path.splitext(os.path.basename(flow_acc))[0], a=str(accumulation_value) ), waterRst, template=mdt, api='arcpy' ) if outFormat in vecFormat: stream_to_feature(waterRst, dire_rst, waterbodies) return waterbodies else: return waterRst
def viewshed_by_feat_class2(inRaster, observerDataset, feat_class_folder, output_folder, snapRst=None, visibilityRadius=20000, epsg=3763): """ See for each feature class in a folder if it is possible to see a interest object from all poins in each feature class Why this method is different from viewshed_by_feat_class? viewshed_by_feat_class uses viewshed tool of ArcGIS; This one will calculate the visibility point by point, when the script identifies that one point is observable from another, it stops. TO BE MANTAINED? """ import arcpy import numpy import os from glass.oss.ops import create_folder from glass.prop.ff import vector_formats, raster_formats from glass.cpu.arcg.lyr import feat_lyr from glass.prop.rst import get_cell_coord from glass.prop.ext import rst_ext from glass.prop.rst import rst_shape, rst_distinct, get_nodata, get_cellsize from glass.anls.prox.bf import _buffer from glass.cpu.arcg.mng.rst.proc import clip_raster from glass.cpu.arcg.spanlst.surf import viewshed from glass.cpu.arcg.spanlst.rcls import reclassify from glass.cpu.arcg._3D.view import line_of_sight from glass.to.rst import shp_to_raster from glass.to.rst.arcg import array_to_raster from glass.to.shp.arcg import geomArray_to_fc from glass.fm.rst import toarray_varcmap as rst_to_array arcpy.CheckOutExtension('Spatial') arcpy.env.overwriteOutput = True # Check if observerDataset is a Raster or a Feature Class RASTER_FORMATS = raster_formats() VECTOR_FORMATS = vector_formats() observerFormat = os.path.splitext(observerDataset)[1] if observerFormat in VECTOR_FORMATS: from glass.cpu.arcg.anls.exct import clip elif observerFormat in RASTER_FORMATS: from glass.to.shp.arcg import rst_to_pnt from glass.to.shp import rst_to_polyg # If raster, get CELLSIZE of the observer dataset CELLSIZE = get_cellsize(observerDataset, gisApi='arcpy') REF_CELLSIZE = 500 from glass.cpu.arcg.mng.sample import fishnet from glass.cpu.arcg.anls.ovlay import erase from glass.cpu.arcg.mng.feat import feat_to_pnt else: raise ValueError(('Could not identify if observerDataset is a raster ' 'or a feature class')) # Create workspace for temporary files wTmp = create_folder(os.path.join(output_folder, 'tempfiles')) # When clipping the observerDataset (when it is a raster), there is a change # of obtaining a raster with more values than the original raster # Check values of the observerDataset UNIQUEVALUES = [] if observerFormat in RASTER_FORMATS: for line in arcpy.SearchCursor(observerDataset): # TODO: Raster could not have attribute table value = int(line.getValue("Value")) if value not in UNIQUEVALUES: UNIQUEVALUES.append(value) else: continue # List feature classes arcpy.env.workspace = feat_class_folder fclasses = arcpy.ListFeatureClasses() for fc in fclasses: # Create Buffer fcBuffer = _buffer( fc, visibilityRadius, os.path.join(wTmp, os.path.basename(fc)), ) # Clip inRaster clipInRst = clip_raster(inRaster, fcBuffer, os.path.join( wTmp, 'dem_{}{}'.format( os.path.splitext( os.path.basename(fc))[0], os.path.splitext(inRaster)[1])), snap=snapRst, clipGeom=True) # Clip observerDataset # If Raster, convert to points if observerDataset in VECTOR_FORMATS: clipObs = clip( observerDataset, fcBuffer, os.path.join( wTmp, 'obs_{}{}'.format( os.path.splitext(os.path.basename(fc))[0], os.path.splitext(observerDataset)[1]))) elif observerFormat in RASTER_FORMATS: # Clip Raster clipTmp = clip_raster( observerDataset, fcBuffer, os.path.join( wTmp, 'obs_{}{}'.format( os.path.splitext(os.path.basename(fc))[0], os.path.splitext(observerDataset)[1])), snap=snapRst, clipGeom=True) # Check if clip has the same values that the original raster RST_UNIQUE = rst_distinct(clipTmp, gisApi='arcpy') if len(RST_UNIQUE) > len(UNIQUEVALUES): # Reclassify raster rules = {} for v in RST_UNIQUE: if v in UNIQUEVALUES: rules[v] = v else: rules[v] = 'NODATA' clipTmp = reclassify( clipTmp, 'Value', rules, os.path.join(wTmp, 'r_{}'.format(os.path.basename(clipTmp))), template=clipTmp) if CELLSIZE < REF_CELLSIZE: # if cellsize if less than REF_CELLSIZE # Change cellsize to REF_CELLSIZE: # 1) Create fishnet REF_CELLSIZE fishNet = fishnet(os.path.join( wTmp, 'fish_{}'.format(os.path.basename(fc))), clipTmp, cellWidth=REF_CELLSIZE, cellHeight=REF_CELLSIZE) # 2) Erase areas with NoData Values # Raster to shp cls_intPolygon = rst_to_polyg( clipTmp, os.path.join(wTmp, 'cls_int_{}'.format(os.path.basename(fc))), gisApi='arcpy') # - Erase areas of the fishnet that have nodata values # in the raster tmpErase = erase( fishNet, cls_intPolygon, os.path.join(wTmp, 'nozones_{}'.format(os.path.basename(fc)))) trueErase = erase( fishNet, tmpErase, os.path.join(wTmp, 'fishint_{}'.format(os.path.basename(fc)))) # 3) Convert erased fishnet to points clipObs = feat_to_pnt( trueErase, os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc))), pnt_position="INSIDE") else: clipObs = rst_to_pnt( clipTmp, os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc)))) # Calculate visibility # Boundary to raster boundRst = shp_to_raster( fc, 'FID', CELLSIZE, None, os.path.join( wTmp, '{}_{}'.format( os.path.splitext(os.path.basename(fc))[0], os.path.splitext(observerDataset)[1])), snap=clipInRst, api='arcpy') noDataVal = get_nodata(boundRst, gisApi='arcpy') boundArray = rst_to_array(boundRst) # Raster to array # For each cell, get cell position and create line of sight shape = rst_shape(boundRst, gisApi='arcpy') xmin, xmax, ymin, ymax = rst_ext(boundRst, gisApi='arcpy2') visibilityArray = numpy.zeros((shape[0], shape[1])) numpy.copyto(visibilityArray, boundArray, 'unsafe', boundArray == noDataVal) for l in range(len(visibilityArray)): for c in range(len(visibilityArray[l])): if visibilityArray[l][c] == noDataVal: continue # Get cell position x, y = get_cell_coord(l, c, xmin, ymin, CELLSIZE, CELLSIZE) # Get Line of sight cursor = arcpy.SearchCursor(clipObs) for line in cursor: FID = line.getValue("FID") geom = line.Shape.centroid sightArray = [ { "FID": 0, "GEOM": [(x, y), (geom.X, geom.Y)] }, ] lineSight = geomArray_to_fc( sightArray, os.path.join( wTmp, 'ls_{}_{}_{}_{}{}'.format( os.path.splitext(os.path.basename(fc))[0], str(l), str(c), str(FID), os.path.splitext(fc)[1])), "POLYLINE", epsg) lineSightRes = line_of_sight( clipInRst, lineSight, os.path.join( wTmp, 'lsr_{}_{}_{}_{}{}'.format( os.path.splitext(os.path.basename(fc))[0], str(l), str(c), str(FID), os.path.splitext(fc)[1]))) lyrLineSight = feat_lyr(lineSightRes) cs = arcpy.SearchCursor(lyrLineSight) lnh = cs.next() cnt = 0 while cnt == 0: try: vis = lnh.getValue("TarIsVis") except: pass cnt += 1 if vis == 1: visibilityArray[l][c] = 1 break else: continue # Generate Raster with visibility data visibilityRst = array_to_raster( visibilityArray, xmin, CELLSIZE, CELLSIZE, os.path.join( output_folder, 'vis_{}{}'.format( os.path.splitext(os.path.basename(fc))[0], os.path.splitext(clipInRst)[1]))) return output_folder
def euclidean_distance(shpRst, cellsize, outRst, template=None, boundary=None, snap=None): """ Euclidean distance from Spatial Analyst """ from arcpy import env from arcpy.sa import * import os arcpy.CheckOutExtension('Spatial') from glass.prop.ff import vector_formats, raster_formats from glass.cpu.arcg.lyr import feat_lyr, rst_lyr path_to_output = outRst if not boundary else \ os.path.join( os.path.dirname(outRst), '{n}_ext{f}'.format( n=os.path.splitext(os.path.basename(outRst))[0], f=os.path.splitext(os.path.basename(outRst))[1] ) ) inputFormat = os.path.splitext(shpRst)[1] if inputFormat in vector_formats(): inLyr = feat_lyr(shpRst) elif inputFormat in raster_formats(): inLyr = rst_lyr(shpRst) else: raise ValueError( 'Could not identify if shpRst is a feature class or a raster') if template: tempEnvironment0 = env.extent env.extent = template if snap: tempSnap = env.snapRaster env.snapRaster = snap outEucDistance = EucDistance(inLyr, "", cellsize, "") outEucDistance.save(path_to_output) if template: env.extent = tempEnvironment0 if snap: env.snapRaster = tempSnap if boundary: from glass.cpu.arcg.mng.rst.proc import clip_raster clipLyr = feat_lyr(boundary) clip_raster(path_to_output, clipLyr, outRst, template=template, snap=snap)
def viewshed_by_feat_class(inRaster, observerDataset, feat_class_folder, output_folder, snapRst=None, visibilityRadius=50000): """ Run viewshed for each feature class in a folder observerDataset should be a raster or a point/line feature class; observerDataset and inRaster should have a major extent than each one of the feature class in feat_class_folder A visibilityRadius is necessary to do a buffer of each feature class. Some entity could be outside of the feature class boundary but visible from within the same boundary. Restrictions: * ObserverDataset must have a table if a raster; TO BE MANTAINED? """ import arcpy import os arcpy.CheckOutExtension('Spatial') from glass.oss.ops import create_folder from glass.prop.ff import vector_formats, raster_formats from glass.prop.rst import get_cellsize, rst_distinct from glass.anls.prox.bf import _buffer from glass.cpu.arcg.mng.rst.proc import clip_raster from glass.cpu.arcg.spanlst.surf import viewshed from glass.cpu.arcg.spanlst.rcls import reclassify # Check if observerDataset is a Raster or a Feature Class # Import methods to clip obserserverDataset RASTER_FORMATS = raster_formats() VECTOR_FORMATS = vector_formats() observerFormat = os.path.splitext(observerDataset)[1] if observerFormat in VECTOR_FORMATS: from glass.cpu.arcg.anls.exct import clip elif observerFormat in RASTER_FORMATS: from glass.to.shp.arcg import rst_to_pnt from glass.to.shp import rst_to_polyg # If Raster, get CELLSIZE of the observer dataset CELLSIZE = get_cellsize(observerDataset, gisApi='arcpy') REF_CELLSIZE = 500 from glass.cpu.arcg.mng.sample import fishnet from glass.cpu.arcg.anls.ovlay import erase from glass.cpu.arcg.mng.feat import feat_to_pnt else: raise ValueError(('Could not identify if observerDataset ' 'is a raster or a feature class')) # Create workspace for temporary files wTmp = create_folder(os.path.join(output_folder, 'tempfiles')) # When clipping the observerDataset (when it is a raster), there is a change # of obtaining a raster with more values than the original raster # Check values of the observerDataset UNIQUEVALUES = [] if observerFormat in RASTER_FORMATS: for line in arcpy.SearchCursor(observerDataset): value = int(line.getValue("Value")) if value not in UNIQUEVALUES: UNIQUEVALUES.append(value) else: continue # List feature classes arcpy.env.workspace = feat_class_folder fclasses = arcpy.ListFeatureClasses() for fc in fclasses: # Create Buffer fcBuffer = _buffer(fc, visibilityRadius, os.path.join(wTmp, os.path.basename(fc)), api='arcpy') # Clip inRaster clipInRst = clip_raster(inRaster, fcBuffer, os.path.join( wTmp, 'inrst_{}{}'.format( os.path.splitext( os.path.basename(fc))[0], os.path.splitext(inRaster)[1])), snap=snapRst, clipGeom=True) # Clip observerDataset # If Raster, convert to points if observerFormat in VECTOR_FORMATS: clipObs = clip( observerDataset, fcBuffer, os.path.join( wTmp, 'obs_{}{}'.format( os.path.splitext(os.path.basename(fc))[0], os.path.splitext(observerDataset)[1]))) elif observerFormat in RASTER_FORMATS: # Clip raster clipTmp = clip_raster( observerDataset, fcBuffer, os.path.join( wTmp, 'obs_{}{}'.format( os.path.splitext(os.path.basename(fc))[0], os.path.splitext(observerDataset)[1])), snap=snapRst, clipGeom=None) # Check if clip has the same values as the original raster RST_UNIQUE = rst_distinct(clipTmp, gisApi='arcpy') if len(RST_UNIQUE) > len(UNIQUEVALUES): # Reclassify raster rules = {} for v in RST_UNIQUE: if v in UNIQUEVALUES: rules[v] = v else: rules[v] = 'NODATA' clipTmp = reclassify( clipTmp, 'Value', rules, os.path.join(wTmp, 'r_{}'.format(os.path.basename(clipTmp))), template=clipTmp) if CELLSIZE < REF_CELLSIZE: # if cellsize if less than REF_CELLSIZE # Change cellsize to REF_CELLSIZE: # 1) Create fishnet REF_CELLSIZE fishNet = fishnet(os.path.join( wTmp, 'fish_{}'.format(os.path.basename(fc))), clipTmp, cellWidth=REF_CELLSIZE, cellHeight=REF_CELLSIZE) # 2) Erase areas with NoData values # - Raster to shp cls_intPolygon = rst_to_polyg( clipTmp, os.path.join(wTmp, 'cls_int_{}'.format(os.path.basename(fc))), gisApi='arcpy') # - Erase areas of the fishnet that agrees with nodata values in the raster tmpErase = erase( fishNet, cls_intPolygon, os.path.join(wTmp, 'nozones_{}'.format(os.path.basename(fc)))) trueErase = erase( fishNet, tmpErase, os.path.join(wTmp, 'fishint_{}'.format(os.path.basename(fc)))) # 3) Convert erased fishnet to points clipObs = feat_to_pnt( trueErase, os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc))), pnt_position="INSIDE") # Else - simple conversion to points else: clipObs = rst_to_pnt( clipTmp, os.path.join(wTmp, 'obs_{}'.format(os.path.basename(fc)))) # Run viewshed viewshed( clipInRst, clipObs, os.path.join( output_folder, 'vis_{}{}'.format( os.path.splitext(os.path.basename(fc))[0], os.path.splitext(clipInRst)[1])))