def rnd_points_with_dist_from_points(otherPnt, rndPnt, NPnt, distFromOtherPnt, boundary, distRndTolerance=None): """ Create NRandom Points with a distance of X from other Points """ import os from glass.oss import get_filename from glass.cpu.arcg.anls.ovlay import erase from glass.anls.prox.bf import _buffer WORKSPACE = os.path.dirname(rndPnt) # Create Buffer bfShp = _buffer(otherPnt, distFromOtherPnt, os.path.join( WORKSPACE, "{}_buffer.shp".format(get_filename(otherPnt))), dissolve="ALL", api='arcpy') # Erase Boundary deleting areas where we want no points erased = erase( boundary, bfShp, os.path.join(WORKSPACE, "{}_erase.shp".format(get_filename(boundary)))) # Create Random Points return rnd_points(rndPnt, NPnt, erased, distTolerance=distRndTolerance)
def range_score(raster, output, MAX=True, __template=None): """ Calculate a Range Score of a Raster If Max, major values will be the major values in the normalized raster; Else, major values will be the minor values in the normalizes raster. """ import os from glass.oss import get_filename from glass.cpu.arcg.lyr import rst_lyr from glass.prop.rst import rst_stats from glass.spanlst.algebra import rstcalc lyr = rst_lyr(raster) __max = rst_stats(lyr, api='arcpy')["MAX"] __min = rst_stats(lyr, api='arcpy')["MIN"] express = '({rst} - {_min}) / ({_max} - {_min})' if MAX else \ '({_max} - {rst}) / ({_max} - {_min})' rstcalc(express.format(_min=str(__min), _max=str(__max), rst=get_filename(raster)), output, api='arcpy') return output
def maximum_score(raster, output, MAX=True, __template=None): """ Calculate a Maximum Score of a Raster If Max, major values will be the major values in the normalized raster; Else, major values will be the minor values in the normalizes raster. """ import os from glass.oss import get_filename from glass.cpu.arcg.lyr import rst_lyr from glass.prop.rst import rst_stats from glass.spanlst.algebra import rstcalc lyr = rst_lyr(raster) __max = rst_stats(lyr, api='arcpy')["MAX"] express = '{rst} / {_max}' if MAX else '1 - ({rst} / {_max})' rstcalc(express.format(rst=get_filename(raster), _max=str(__max)), output, template=__template, api='arcpy') return output
def generalize_obs_points_forFolder(FolderRst, refCell, outFolder): """ Loop for generalize_obs_points """ import arcpy import os from glass.oss import get_filename from glass.oss.ops import create_folder from glass.prop.rst import rst_distinct arcpy.env.workspace = FolderRst rasters = arcpy.ListRasters() wTmp = create_folder(os.path.join(outFolder, 'tmp')) for r in rasters: # Check if raster has data val = rst_distinct(r, gisApi='arcpy') if not len(val): continue # Generate observer points generalize_obs_points(r, refCell, os.path.join(outFolder, "{}.shp".format(get_filename(r))), workspace=wTmp) return outFolder
def generalize_obs_points(rst, ref_cellsize, output, workspace=None): """ We have one raster, each pixel is an observer point. If we have a raster with many pixels, viewshed will not run in a short time period. As result, we have to reduce the number of observer points. This script accomplish the above using a fishnet based approach """ import os from glass.oss import get_filename from glass.oss.ops import create_folder from glass.cpu.arcg.anls.ovlay import erase from glass.prop.rst import get_cellsize from glass.cpu.arcg.mng.feat import feat_to_pnt from glass.cpu.arcg.mng.sample import fishnet from glass.to.shp import rst_to_polyg # 0 - Check cellsize, raster cellsize should be lower than refCellsize CELLSIZE = get_cellsize(rst, xy=True, bnd=None, gisApi='arcpy') if CELLSIZE >= ref_cellsize: raise ValueError( ("{} cellsize is not lower than ref_cellsize").format(rst)) wTmp = workspace if workspace else create_folder( os.path.join(os.path.dirname(output), 'tmp'), overwrite=True) BASENAME = get_filename(rst) # Change cellsize to REF_CELLSIZE # 1) Create fishnet with REF_CELLSIZE fishNet = fishnet(os.path.join(wTmp, "fish_{}.shp".format(BASENAME)), rst, cellWidth=ref_cellsize, cellHeight=ref_cellsize) # 2) Erase areas with NoData values # - Raster to shp cls_intPolygon = rst_to_polyg(rst, os.path.join( wTmp, 'clsint_{}.shp'.format(BASENAME)), 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_{}.shp'.format(BASENAME))) trueErase = erase(fishNet, tmpErase, os.path.join(wTmp, 'fishint_{}.shp'.format(BASENAME))) # 3) Convert erased fishnet to points genObs = feat_to_pnt(trueErase, output, pnt_position="INSIDE") return genObs
def TIN_nodata_interpolation(inRst, boundary, prj, cellsize, outRst, workspace=None, template=None): """ Preenche os valores NoData de uma imagem raster usando um TIN """ import os from glass.oss import get_filename from glass.cpu.arcg.lyr import rst_lyr from glass.cpu.arcg.lyr import feat_lyr from glass.cpu.to.shp.arcg import rst_to_pnt from glass.cpu.arcg._3D.mng.tin import create_tin from glass.cpu.to.rst.arcg import tin_to_raster workspace = workspace if workspace else \ os.path.dirname(outRst) # Convert Input Raster to a Point Feature Class rstLyr = rst_lyr(inRst) pntRst = rst_to_pnt( rstLyr, os.path.join(workspace, get_filename(inRstinRst) + '.shp')) # Create TIN pntrstLyr = feat_lyr(pntRst) lmtLyr = feat_lyr(boundary) tinInputs = ('{bound} <None> Soft_Clip <None>;' '{rst_pnt} GRID_CODE Mass_Points <None>') tinOutput = os.path.join(workspace, 'tin_' + get_filename(inRst)) create_tin(tinOutput, prj, tinInputs) return tin_to_raster(tinOutput, cellsize, outRst, template=template)
def rnd_points(rndPntShp, NPoints, whereShp, distTolerance=None): """ Create NRandom Points inside some area and save the result in one file """ import os from glass.oss import get_filename distT = "" if not distTolerance else "{} Meters".format(distTolerance) arcpy.CreateRandomPoints_management(os.path.dirname(rndPntShp), get_filename(rndPntShp), whereShp, "", NPoints, distT, "POINT", "0") return rndPntShp
def generate_obs_points_for_large_viewshed(INTEREST_RASTER, DEM, REF_CELLS, ID_CELLS, OUT_FOLDER, SNAP_RASTER, SRS_EPSG, OBS_PNT_TOLERANCE, PRODUCE_DEM=None, PRODUCE_FROM_INDEX=None): """ Imagine-se que se pretende gerar um raster com a visibilidade a um conjunto de entidades geográficas identificadas num ficheiro raster com o valor 1 (Interest Raster) e que a informação diz respeito a uma extensão considerável, como por exemplo, a extensão de um país. Como é fácil de perceber, isto não pode ser feito executando a ferramenta viewshed uma única vez, consequência do elevado volume de dados. A melhor forma de resolver o problema é segmentar os dados em vários ficheiros, tendo como referência uma Feature Classe constituida por features que constituem parcelas mais pequenas da área total a ser trabalhada - adiante, estas parcelas serão designadas apenas por Células. A ferramenta viewshed poderá depois ser executada de modo parcelar, uma vez para cada conjunto de ficheiros. Este método segmenta/divide os dados originais em partes, permitindo que a viewshed possa ser executada também por partes. Esta divisão seguirá as seguintes regras: * Para cada célula, o DEM deve ser extraído para uma área cuja extensão seja igual à extensão da Célula + 10 Km de tolerância; * Cada célula do Interest Raster será considerada como um ponto de observação. Havendo muitos pixéis no Interest Raster, deverá ser definida uma tolerância em metros, que definirá a distância mínima entre cada ponto de observação. Se esta distância for superior ao cellsize do Interest Raster, haverão menos pontos de observação do que células do Interest Raster, o que reduzirá significativamente a carga do cálculo da viewshed. Claro, esta tolerância deverá ser definida com critério, garantindo que os resultados são válidos. Este script tem duas formas de execução: * com PRODUCE_DEM = None, será feito o pre_processamento; * com PRODUCE_DEM = True, os rasters com as bacias de visibilidade serão criados, tendo por base os ficheiros criados no pre-processamento. """ import os from threading import Thread from glass.cpu.arcg.mng.rst.proc import clip_raster_each_feat_class from glass.cpu.arcg.spanlst.rcls import rcls_folderRaster from glass.cpu.arcg.spanlst.surf import viewshed from glass.fm import tbl_to_obj from glass.oss import get_filename from glass.oss.ops import create_folder from glass.anls.exct import split_shp_by_attr from glass.mng.ext import df_buffer_extent from glass.mng.fld.df import col_distinct # Create workspaces to store data C_CELLS_FLD = os.path.join(OUT_FOLDER, 'cells') RST_TMP = os.path.join(OUT_FOLDER, 'mask_tmp') RST_FLD = os.path.join(OUT_FOLDER, 'mask_rst') B_CELLS_FLD = os.path.join(OUT_FOLDER, 'bf_cells') OBS_FLD = os.path.join(OUT_FOLDER, 'obs_pnt') DEM_RST = os.path.join(OUT_FOLDER, get_filename(DEM)) THRD_MAPS = { "INT_RST": { "CELLS_FLD": create_folder(C_CELLS_FLD, overwrite=None) if not os.path.exists(C_CELLS_FLD) else C_CELLS_FLD, "RST_TMP": create_folder(RST_TMP, overwrite=None) if not os.path.exists(RST_TMP) else RST_TMP, "RST_FLD": create_folder(RST_FLD, overwrite=None) if not os.path.exists(RST_FLD) else RST_FLD, "OBS_FLD": create_folder(OBS_FLD, overwrite=None) if not os.path.exists(OBS_FLD) else OBS_FLD }, "DEM": { "RST_FLD": create_folder(DEM_RST, overwrite=True) if not os.path.exists(DEM_RST) else DEM_RST, "CELLS_FLD": create_folder(B_CELLS_FLD, overwrite=None) if not os.path.exists(B_CELLS_FLD) else B_CELLS_FLD, } } if not PRODUCE_DEM: """ Split data into parts """ """ Split Cells """ def split_cells(f, bf, of): if bf == "DEM": _f = df_buffer_extent(f, SRS_EPSG, 10000, os.path.join(OUT_FOLDER, 'bf_cells.shp')) else: _f = f split_shp_by_attr(_f, ID_CELLS, of["CELLS_FLD"], _format='.shp') thrds = [ Thread(name="split-{}".format(k), target=split_cells, args=(REF_CELLS, k, THRD_MAPS[k])) for k in THRD_MAPS ] for t in thrds: t.start() for t in thrds: t.join() """ Clip INTEREST RASTER for all cells in CELLS_FLD and BF_CELLS_FLD """ for key, val in THRD_MAPS.items(): inrst = DEM if key == "DEM" else INTEREST_RASTER clip_raster_each_feat_class( inrst, val["CELLS_FLD"], val["RST_FLD"] if key == "DEM" else val["RST_TMP"], snap=SNAP_RASTER, clipGeometry=True) """ Reclassify Rasters of interest: - For each cell, create a Raster with presence of class and other with ausence of class """ rcls_folderRaster(THRD_MAPS["INT_RST"]["RST_TMP"], { 0: 'NoData', 1: 1 }, THRD_MAPS["INT_RST"]["RST_FLD"]) """ Create Observer points for each raster """ generalize_obs_points_forFolder(THRD_MAPS["INT_RST"]["RST_FLD"], OBS_PNT_TOLERANCE, THRD_MAPS["INT_RST"]["OBS_FLD"]) else: """ Generate Viewsheds """ cellsDf = tbl_to_obj(REF_CELLS) LST_CELLS = col_distinct(cellsDf, ID_CELLS) OBS_REF_NAME = get_filename(REF_CELLS) __LST_CELLS = LST_CELLS if not PRODUCE_FROM_INDEX else LST_CELLS[: PRODUCE_FROM_INDEX] for cell_id in LST_CELLS: OUT_RST = os.path.join(OUT_FOLDER, "vis_{}.tif".format(str(cell_id))) if os.path.exists(OUT_RST): continue DEM_RST = os.path.join( THRD_MAPS["DEM"]["RST_FLD"], "bf_cells_{}.tif".format(str(cell_id)), ) OBS_SHP = os.path.join( THRD_MAPS["INT_RST"]["OBS_FLD"], "{}_{}.shp".format(OBS_REF_NAME, str(int(cell_id)))) if not os.path.join(OBS_SHP): continue viewshed(DEM_RST, OBS_SHP, OUT_RST, snapRaster=DEM_RST, extRaster=DEM_RST)