def execute_SpatializeQ(r_flowdir, str_frompoint, r_flowacc, r_qpts, str_res, interpolation): flowdir = RasterIO(r_flowdir) flowacc = RasterIO(r_flowacc) qpts = RasterIO(r_qpts) Res = RasterIO(r_flowdir, str_res, float, -255) trees = build_trees(flowdir, str_frompoint, Q=qpts, flowacc=flowacc) for tree in trees: # transmitting from upstream point for segment, prev_cs, cs in tree.uptodown_browsepts(): cs.A = float(cs.flowacc) if cs.Q != qpts.nodata: cs.up_ptsA = cs.A cs.up_ptsQ = cs.Q elif prev_cs != None: cs.up_ptsA = prev_cs.up_ptsA cs.up_ptsQ = prev_cs.up_ptsQ else: cs.up_ptsA = 0 cs.up_ptsQ = 0 # transmitting from downstream point for segment, prev_cs, cs in tree.browsepts(): if cs.Q != qpts.nodata: cs.down_ptsA = cs.A cs.down_ptsQ = cs.Q else: if prev_cs != None: cs.down_ptsA = prev_cs.down_ptsA cs.down_ptsQ = prev_cs.down_ptsQ else: cs.down_ptsA = 0 cs.down_ptsQ = 0 if interpolation: cs.alpha = (cs.up_ptsQ - cs.down_ptsQ) / (cs.up_ptsA - cs.down_ptsA) cs.beta = cs.down_ptsQ - cs.alpha * cs.down_ptsA cs.Q = cs.alpha * cs.A + cs.beta else: if cs.down_ptsA == 0: # cas particulier : pas d'interpolation (débit de crue), et extrapolation down cs.Q = cs.up_ptsQ / cs.up_ptsA * cs.A else: cs.Q = cs.down_ptsQ / cs.down_ptsA * cs.A for segment in tree.treesegments(): for pt in segment.get_profile(): Res.setValue(pt.row, pt.col, pt.Q) Res.save() return
def execute_Simple1Dhydraulic(r_flowdir, str_frompoint, r_width, r_zbed, manning, result, r_Q, downstream_s, messages): flowdir = RasterIO(r_flowdir) zbed = RasterIO(r_zbed) width = RasterIO(r_width) Q = RasterIO(r_Q) trees = build_trees(flowdir, str_frompoint, width=width, z=zbed, Q=Q) Result = RasterIO(r_flowdir, result, float, -255) for tree in trees: downstream_end = True # 1D hydraulic calculations for segment, prev_cs, cs in tree.browsepts(): if (cs.width == width.nodata or cs.z==zbed.nodata or cs.Q == Q.nodata): cs.skipped = True if not downstream_end: messages.addErrorMessage("Missing data at "+str(cs.X)+", "+str(cs.Y)) else: cs.skipped = False downstream_end = False cs.n = manning if prev_cs == None or prev_cs.skipped: # downstream cs calculation cs.s = downstream_s manning_solver(cs) cs.v = cs.Q / (cs.width * cs.y) cs.h = cs.z + cs.y + cs.v ** 2 / (2 * g) cs.Fr = cs.v / (g * cs.y) ** 0.5 cs.solver = "manning" cs.type = 0 else: cs_solver(cs, prev_cs) cs.ws = cs.z + cs.y for segment in tree.treesegments(): for pt in segment.get_profile(): if not pt.skipped: Result.setValue(pt.row, pt.col, pt.ws) Result.save() return
def execute_LinearInterpolation(r_flowdir, str_frompoint, r_values, str_results, messages, language="FR"): # Chargement des fichiers flowdir = RasterIO(r_flowdir) bkfatcs = RasterIO(r_values) try: flowdir.checkMatch(bkfatcs) except Exception as e: messages.addErrorMessage(e.message) Result = RasterIO(r_flowdir, str_results, float, -255) # Décompte du nombre de points de départ pour configurer de la barre de progression count = 0 frompointcursor = arcpy.da.SearchCursor(str_frompoint, "OID@") for frompoint in frompointcursor: count += 1 progtext = "Traitement" if language == "EN": progtext = "Processing" arcpy.SetProgressor("step", progtext, 0, count, 1) progres = 0 # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoint, ["OID@", "SHAPE@"]) for frompoint in frompointcursor: # Mise à jour de la barre de progression arcpy.SetProgressorPosition(progres) progres += 1 # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[1].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) intheraster = True # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False listpointsflowpath = [] listdistance = [] listelevation = [] totaldistance = 0 currentdistance = 0 confluence = False # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): currentpoint = pointflowpath() currentpoint.row = currentrow currentpoint.col = currentcol totaldistance = totaldistance + currentdistance currentpoint.flowlength = totaldistance currentpoint.oncs = False # On crée une liste des points d'élévation connue le long de l'écoulement, ainsi qu'une liste associée avec leur distance depuis le point de distance if bkfatcs.getValue(currentrow, currentcol) != bkfatcs.nodata: if confluence: # point après atteinte d'une confluence. On arrête le traitement intheraster = False listdistance.append(totaldistance) listelevation.append(bkfatcs.getValue(currentrow, currentcol)) currentpoint.oncs = True currentpoint.previouscsid = len(listdistance) - 1 if not confluence: listpointsflowpath.append(currentpoint) # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 4): currentrow = currentrow + 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 16): currentcol = currentcol - 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 64): currentrow = currentrow - 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != -255): # Atteinte d'un confluent # On continue encore jusqu'au prochain point confluence = True if len(listdistance) <= 1: # Avertissement si il n'y a qu'un seul (ou aucun) point de données if language == "FR": messages.addWarningMessage( "Point source {0}: pas assez de sections transversales". format(frompoint[0])) else: messages.addWarningMessage( "From point {0}: not enough cross-sections".format( frompoint[0])) else: currentpointnumber = 0 # Traitement pour chaque point le long de l'écoulement for currentpoint in listpointsflowpath: try: if currentpoint.previouscsid == -1: # cas particulier des premiers points avant une cs # on prends la valeur de la premier cs finalvalue = listelevation[0] else: if currentpoint.oncs: # cas particulier : points sur une section transversale finalvalue = listelevation[ currentpoint.previouscsid] else: finalvalue = listelevation[currentpoint.previouscsid]* \ (listdistance[currentpoint.previouscsid + 1] - currentpoint.flowlength)/\ (listdistance[currentpoint.previouscsid+1]-listdistance[currentpoint.previouscsid])\ + listelevation[currentpoint.previouscsid+1]* \ (currentpoint.flowlength - listdistance[currentpoint.previouscsid])/\ (listdistance[currentpoint.previouscsid+1]-listdistance[currentpoint.previouscsid]) except IndexError: # IndexError lorsque l'on est en aval de la dernière section transversales finalvalue = listelevation[-1] Result.setValue(currentpoint.row, currentpoint.col, finalvalue) currentpointnumber = currentpointnumber + 1 Result.save() return
def execute_FloodAndChannel(r_dem, r_elevation, r_flowdir, r_slope, str_frompoints, threshold_slope, threshold_growth, maxiter, str_output, messages, language="FR"): # Chargement des fichiers dem = RasterIO(r_dem) elevation = RasterIO(r_elevation) slope = None if r_slope is not None: slope = RasterIO(r_slope) flowdir = RasterIO(r_flowdir) try: dem.checkMatch(flowdir) dem.checkMatch(elevation) if slope is not None: dem.checkMatch(slope) except Exception as e: messages.addErrorMessage(e.message) # Fichier temporaire créé dans le "Scratch folder" randomname = binascii.hexlify(os.urandom(6)).decode() temp_flood = arcpy.env.scratchWorkspace + "\\" + str(randomname) Result = RasterIO(r_dem, temp_flood, float, -255) # Décompte du nombre de points de départ pour configurer de la barre de progression frompointcursor = arcpy.da.SearchCursor(str_frompoints, "SHAPE@") count = 0 for frompoint in frompointcursor: count += 1 progtext = "Traitement" if language == "EN": progtext = "Processing" arcpy.SetProgressor("step", progtext, 0, count, 1) progres = 0 # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoints, ["SHAPE@", "OID@"]) for frompoint in frompointcursor: # Mise à jour de la barre de progression arcpy.SetProgressorPosition(progres) progres += 1 # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[0].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) intheraster = True # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False listnewcells = [] # Première itération: on ajoute les cellules pour la rivière, le long de l'écoulement while (intheraster): point = pointflowpath() point.row = currentrow point.col = currentcol point.elev = elevation.getValue(currentrow, currentcol) listnewcells.append(point) Result.setValue(currentrow, currentcol, point.elev) # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 if (direction == 4): currentrow = currentrow + 1 if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 if (direction == 16): currentcol = currentcol - 1 if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 if (direction == 64): currentrow = currentrow - 1 if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != Result.nodata): # Atteinte d'un confluent intheraster = False lengthflowpath = len(listnewcells) # Itération réalisée jusqu'à atteinte du seuil de croissance négligeable, avec aggrandissement de la largeur d'une cellule à chaque itération iteration = 0 while ((float(len(listnewcells)) / float(lengthflowpath)) >= threshold_growth) and iteration < maxiter: currentlistnewcells = [] iteration += 1 # Pour chaque cellule que l'on a ajoutée à l'itération précédente... while (len(listnewcells) > 0): currentpoint = listnewcells.pop() # ... on test les cellules voisines for i in range(1, 5): neighbourcol = currentpoint.col neighbourrow = currentpoint.row if i == 1: neighbourcol += 1 elif i == 2: neighbourcol -= 1 elif i == 3: neighbourrow += 1 elif i == 4: neighbourrow -= 1 try: # Si la cellule voisine existe et n'a pas déjà été testée... if (Result.getValue(neighbourrow, neighbourcol) == Result.nodata) and dem.getValue( neighbourrow, neighbourcol) != dem.nodata: testslope = True if slope is not None: testslope = slope.getValue( neighbourrow, neighbourcol) < threshold_slope # ... on teste si la cellule testée est dans le chenal / inondée ... if (dem.getValue(neighbourrow, neighbourcol) < currentpoint.elev) and testslope: #... auquel cas on mets à jour le fichier de résultat et la liste des cellules ajoutées par l'itération en cours Result.setValue(neighbourrow, neighbourcol, currentpoint.elev) point = pointflowpath() point.row = neighbourrow point.col = neighbourcol point.elev = currentpoint.elev currentlistnewcells.append(point) else: # Les cellules testées négativement sont mises à -999 pour éviter de les tester à nouveau Result.setValue(neighbourrow, neighbourcol, -999) except IndexError: # Exception déclenchée et à ignorer lorsque l'on est sur le bord du raster pass listnewcells.extend(currentlistnewcells) # On supprime les -999 du résultat final Result.save() raster_res = arcpy.sa.SetNull(temp_flood, temp_flood, "VALUE = -999") raster_res.save(str_output) arcpy.Delete_management(temp_flood) return
def execute_BedAssessment(r_flowdird4, str_frompoint, r_width, r_zwater, manning, result, r_Q, downstream_s, messages): flowdir = RasterIO(r_flowdird4) zwater = RasterIO(r_zwater) width = RasterIO(r_width) Q = RasterIO(r_Q) trees = build_trees(flowdir, str_frompoint, width=width, wslidar=zwater, Q=Q) Result = RasterIO(r_flowdird4, result, float, -255) for tree in trees: enditeration = False iteration = 0 downstream_end = True while not enditeration: iteration += 1 print (iteration) # 1D hydraulic calculations prevsegid = 0 for segment, prev_cs, cs in tree.browsepts(): if (cs.width == width.nodata or cs.wslidar==zwater.nodata or cs.Q == Q.nodata): cs.skipped = True if not downstream_end and iteration == 1: messages.addWarningMessage("Missing data at "+str(cs.X)+", "+str(cs.Y)) else: cs.skipped = False downstream_end = False cs.n = manning if iteration == 1: cs.z = cs.wslidar cs.ws = cs.wslidar if prev_cs == None or prev_cs.skipped: # downstream cs calculation cs.s = downstream_s manning_solver(cs) cs.v = cs.Q / (cs.width * cs.y) cs.h = cs.z + cs.y + cs.v ** 2 / (2 * g) cs.Fr = cs.v / (g * cs.y) ** 0.5 cs.solver = "manning" cs.type = 0 else: cs_solver(cs, prev_cs) cs.prev_ws = cs.ws cs.ws = cs.z + cs.y cs.dif = cs.ws - cs.wslidar prevsegid = segment.id corrections = [] # down to up for segment, prev_cs, cs in tree.browsepts(): if not cs.skipped: if prev_cs != None and not prev_cs.skipped: if prev_cs.z_fill > cs.z: if prev_cs.z == prev_cs.z_fill: # first backwater cell correction = [] corrections.append(correction) cs.idcorrection = len(corrections) - 1 else: correction = corrections[prev_cs.idcorrection] cs.idcorrection = prev_cs.idcorrection cs.z_fill = prev_cs.z_fill correction.append(cs) else: cs.z_fill = cs.z correction = [] correction.append(cs) corrections.append(correction) cs.idcorrection = len(corrections) - 1 else: cs.z_fill = cs.z correction = [] correction.append(cs) corrections.append(correction) cs.idcorrection = len(corrections) - 1 enditeration = True for correction in corrections: sumdif = 0 sumdifws = 0 for cscorrect in correction: sumdif += cscorrect.dif sumdifws += cscorrect.ws - cscorrect.prev_ws correcteddif = sumdif / len(correction) difws = abs(sumdifws) / len(correction) if difws > 0.01: for cscorrect in correction: cscorrect.z = cscorrect.z - correcteddif enditeration = False for segment in tree.treesegments(): for pt in segment.get_profile(): if not pt.skipped: Result.setValue(pt.row, pt.col, pt.z) Result.save() return
def execute_orientedCS(r_flowdir, str_frompoints, str_ptscs, smoothingdistance, str_cs, messages, language="FR"): arcpy.env.outputCoordinateSystem = r_flowdir.spatialReference # Chargement des fichiers flowdir = RasterIO(r_flowdir) arcpy.env.extent = r_flowdir arcpy.env.snapRaster = r_flowdir randomname = binascii.hexlify(os.urandom(6)).decode() temp_cs2 = arcpy.env.scratchWorkspace + "\\" + str(randomname) arcpy.PointToRaster_conversion(str_ptscs, arcpy.Describe(str_ptscs).OIDFieldName, temp_cs2, cellsize=r_flowdir) temprastercs = RasterIO(arcpy.Raster(temp_cs2)) Result = RasterIO(r_flowdir, str_cs, float, -255) # Décompte du nombre de points de départ pour configurer de la barre de progression frompointcursor = arcpy.da.SearchCursor(str_frompoints, "OID@") count = 0 for frompoint in frompointcursor: count += 1 progtext = "Calcul de l'orientation des sections transversales" if language == "EN": progtext = "Processing" arcpy.SetProgressor("step", progtext, 0, count, 1) progres = 0 # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoints, "SHAPE@") for frompoint in frompointcursor: # Mise à jour de la barre de progression arcpy.SetProgressorPosition(progres) progres += 1 # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[0].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters intheraster = True if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False totaldistance = 0 currentdistance = 0 confluencedist = 0 listpointsflowpath = [] afterconfluence = False # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): # On stock différentes informations sur le point dans listpointsflowpath currentpoint = pointflowpath() currentpoint.row = currentrow currentpoint.col = currentcol currentpoint.X = flowdir.ColtoX(currentcol) currentpoint.Y = flowdir.RowtoY(currentrow) currentpoint.addeddistance = currentdistance totaldistance = totaldistance + currentdistance currentpoint.distance = totaldistance listpointsflowpath.append(currentpoint) # Les points traité sont mis à -999 (cela permet la détection des confluences) if not afterconfluence: Result.setValue(currentrow, currentcol, -999) # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 4): currentrow = currentrow + 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 16): currentcol = currentcol - 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 64): currentrow = currentrow - 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != Result.nodata): # Atteinte d'un point déjà traité if confluencedist == 0: confluencedist = totaldistance + currentdistance afterconfluence = True # On continue encore sur la moitié de la distance de calcul de la pente après le confluent if (totaldistance + currentdistance - confluencedist) > smoothingdistance / 2: intheraster = False currentpointnumber = 0 # Traitement effectué sur la liste des points le long de l'écoulement while (currentpointnumber < len(listpointsflowpath)): currentpoint = listpointsflowpath[currentpointnumber] if temprastercs.getValue(currentpoint.row, currentpoint.col) != temprastercs.nodata: # Point pour lequel on doit calculer l'orientation de la section transversale listXforregression = [] listYforregression = [] listXforregression.append(currentpoint.X) listYforregression.append(currentpoint.Y) distancefromcurrentpoint = 0 nbcellsfromcurrentpoint = 0 try: # on ajoute dans listpointforregression les points situés avant le point courant, jusqu'à la distance souhaitée while (distancefromcurrentpoint <= smoothingdistance / 2): nbcellsfromcurrentpoint = nbcellsfromcurrentpoint - 1 if (currentpointnumber + nbcellsfromcurrentpoint > 0): distancefromcurrentpoint = distancefromcurrentpoint + listpointsflowpath[ currentpointnumber + nbcellsfromcurrentpoint].addeddistance listXforregression.append( listpointsflowpath[currentpointnumber + nbcellsfromcurrentpoint].X) listYforregression.append( listpointsflowpath[currentpointnumber + nbcellsfromcurrentpoint].Y) else: raise IndexError distancefromcurrentpoint = 0 nbcellsfromcurrentpoint = 0 # on ajoute également les points situé après le point courant, jusqu'à la distance souhaitée while (distancefromcurrentpoint < smoothingdistance / 2): nbcellsfromcurrentpoint = nbcellsfromcurrentpoint + 1 distancefromcurrentpoint = distancefromcurrentpoint + listpointsflowpath[ currentpointnumber + nbcellsfromcurrentpoint].addeddistance listXforregression.append( listpointsflowpath[currentpointnumber + nbcellsfromcurrentpoint].X) listYforregression.append( listpointsflowpath[currentpointnumber + nbcellsfromcurrentpoint].Y) # Variance et covariance prises avec 0 degrés de liberté varx = numpy.var(listXforregression) vary = numpy.var(listYforregression) covarxy = numpy.cov(listXforregression, listYforregression, bias=True)[0][1] slope = 0 if (covarxy != 0 and varx > 0 and vary > 0): # Formule pour la régression par axe majeur : Legendre et Legendre, 1998, Numerical Ecology, 2ème édition (p.507) slope = (vary - varx + math.sqrt( (vary - varx)**2 + 4 * covarxy**2)) / (2 * covarxy) angle = math.atan2(slope, 1) # angle perpendiculaire à l'écoulement: angle = angle + math.pi / 2 if (angle > math.pi): angle = angle - 2 * math.pi else: if varx == 0: angle = 0 elif vary == 0: angle = math.pi / 2 else: # la covariance est nulle # on compare l'évolution en x et en y entre le premier et le dernier point if (listXforregression[0] - listXforregression[-1] ) > (listYforregression[0] - listYforregression[-1]): angle = math.pi / 2 else: angle = 0 Result.setValue(currentpoint.row, currentpoint.col, angle) except IndexError: pass currentpointnumber = currentpointnumber + 1 Result.save() # On supprime les -999 du résultat final raster_res = arcpy.sa.SetNull(str_cs, str_cs, "VALUE = -999") raster_res.save(str_cs) # On supprime le fichier temporaire arcpy.Delete_management(temp_cs2) return
def execute_WSprofile(r_flowdir, str_frompoint, r_z, str_zws, messages): flowdir = RasterIO(r_flowdir) z = RasterIO(r_z) trees = build_trees(flowdir, str_frompoint, z=z) zws = RasterIO(r_flowdir, str_zws, float, -255) for tree in trees: goodslope = False iteration = 0 while not goodslope: iteration += 1 corrections = [] # down to up for segment, prev_cs, cs in tree.browsepts(): if prev_cs is not None: cs.z_fill = max(prev_cs.z_fill, cs.z) else: cs.z_fill = cs.z if iteration == 1: cs.originalfill = cs.z_fill # z_breach à None permet le bon breach pour les parties parcourues plusieurs fois cs.z_breach = None # up to down for segment, prev_cs, cs in tree.uptodown_browsepts(): if prev_cs is not None: if cs.z_breach is not None: cs.z_breach = min(prev_cs.z_breach, cs.z, cs.z_breach) else: cs.z_breach = min(prev_cs.z_breach, cs.z) else: cs.z_breach = cs.z if iteration == 1: cs.originalbreach = cs.z_breach # down to up for segment, prev_cs, cs in tree.browsepts(): if prev_cs is not None: if cs.z_breach == prev_cs.z_breach and cs.z_fill == prev_cs.z_fill: # ajout de la cs à la correction correction = corrections[prev_cs.idcorrection] correction.append(cs) cs.idcorrection = prev_cs.idcorrection else: # nouvelle correction correction = [] correction.append(cs) corrections.append(correction) cs.idcorrection = len(corrections) - 1 else: correction = [] correction.append(cs) corrections.append(correction) cs.idcorrection = len(corrections) - 1 for correction in corrections: sumz2 = 0 for cscorrect in correction: sumz2 += cscorrect.z**2 correctedz = (sumz2 / len(correction))**0.5 for cscorrect in correction: cscorrect.z = correctedz # test goodslope goodslope = True # up to down for segment, prev_cs, cs in tree.uptodown_browsepts(): if prev_cs != None and cs.z > prev_cs.z: goodslope = False for segment in tree.treesegments(): for pt in segment.get_profile(): zws.setValue(pt.row, pt.col, pt.z) zws.save() return
def execute_BankfullAtCS(r_dem, r_flowdir, str_frompoints, r_cs, p_detect, thresholdz, increment, str_bkf, messages, language = "FR"): # Chargement des fichiers dem = RasterIO(r_dem) flowdir = RasterIO(r_flowdir) cs = RasterIO(r_cs) try: dem.checkMatch(flowdir) dem.checkMatch(cs) except Exception as e: messages.addErrorMessage(str(e)) Result = RasterIO(r_dem, str_bkf, float,-255) # Décompte du nombre de points de départ pour configurer de la barre de progression frompointcursor = arcpy.da.SearchCursor(str_frompoints, "OID@") count = 0 for frompoint in frompointcursor: count += 1 progtext= "Calcul des élévations plein-bord aux sections transversales" if language == "EN": progtext = "Computing elevation at cross-sections" arcpy.SetProgressor("step", progtext, 0, count, 1) progres = 0 # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoints, "SHAPE@") for frompoint in frompointcursor: # Mise à jour de la barre de progression arcpy.SetProgressorPosition(progres) progres += 1 # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[0].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) intheraster = True # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters if currentcol<0 or currentcol>=flowdir.raster.width or currentrow<0 or currentrow>= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): # Traitement effectué sur chaque section transversale if cs.getValue(currentrow,currentcol) != cs.nodata: zmin = dem.getValue(currentrow,currentcol) angle = cs.getValue(currentrow,currentcol) MaxHydroH = 0 HydroH = 0 stophydroh = False previouslisth = [] previouslisth.append(zmin) previousstep = 0 prevz = zmin previouslisth2 = [] previouslisth2.append(zmin) previousstep2 = 0 prevz2 = zmin n = 4 # itérations, par incrément de 10 cm while n < (thresholdz/increment) and not stophydroh : n += 1 # currentz : élévation plein-bord testée currentz = zmin + increment*n listh = list(previouslisth) step = previousstep stop = False # Déplacement le long de la section transversale while not stop: step += 1 # calcul de la ligne et de la colonne du prochain point dans l'axe de la section transversale if (angle > math.pi / 4 and angle < 3 * math.pi / 4): rowinc = -step colinc = int(math.cos(angle)*step) else: colinc = step rowinc = -int(math.sin(angle)*step) if angle > 3 * math.pi / 4: rowinc = -rowinc # localz : élévation du sol pour le point testé le long de la section transversale localz = dem.getValue(currentrow + rowinc, currentcol + colinc) # on arrête d'avancer le long de la section transversale quand l'élévation devient plus grande que l'élévation plein-bord testée (ou si on sort du raster) if localz != dem.nodata: if localz < prevz: localz = prevz if localz >= currentz: stop = True prevz = localz else: stop = True listh.append(localz) if(len(listh)>2): previousstep = step -1 previouslisth = listh[:len(listh)-1] sumh = 0 # Pour toutes les élévations sauf la première for i in range(1,len(listh)): if i<len(listh)-1: # Toutes les élévations sauf la dernière. # Aire = panneau trapezoidale sumh+= (currentz-listh[i-1]+currentz-listh[i])/2 elif listh[i]!=dem.nodata: # Dernière élévation : plus haute que currentz. # Aire = formule pour le petit triangle sumh += (currentz-listh[i-1])*(currentz-listh[i-1])/(listh[i]-listh[i-1])/2 step -= 1 step += (currentz - listh[i - 1]) / (listh[i] - listh[i - 1]) else: # Dernière élévation : No Data # Pas d'aire calculée pour ce panneau step-=1 # on répète les opérations précédentes en progressant dans l'autre sens le long de la section transversale listh = list(previouslisth2) step2 = previousstep2 stop = False while not stop: step2 += 1 if (angle > math.pi / 4 and angle < 3 * math.pi / 4): rowinc = -step2 colinc = int(math.cos(angle) * step2) else: colinc = step2 rowinc = -int(math.sin(angle) * step2) if angle > 3 * math.pi / 4: rowinc = -rowinc localz = dem.getValue(currentrow - rowinc, currentcol - colinc) if localz != dem.nodata: if localz < prevz2: localz = prevz2 if localz >= currentz: stop = True prevz2 = localz else: stop = True listh.append(localz) if(len(listh)>2): previousstep2 = step2 -1 previouslisth2 = listh[:len(listh)-1] sumh2 = 0 for i in range(1, len(listh)): if i < len(listh) - 1: sumh2 += (currentz - listh[i - 1] + currentz - listh[i]) / 2 elif listh[i] != dem.nodata: sumh2 += (currentz - listh[i - 1]) * (currentz - listh[i - 1]) / ( listh[i] - listh[i - 1]) / 2 step2 -= 1 step2 += (currentz - listh[i - 1]) / (listh[i] - listh[i - 1]) else: step2-=1 # Calcul de la profondeur moyenne # Note: erreur de +1 au lieu de -1 ds la version EPRI1 HydroH = (sumh + sumh2) / (step + step2) # Le critère pour détecter le niveau plein-bord est-il respecté ? if (HydroH < (1-p_detect/100)*MaxHydroH): # si oui, on prends la dernière élévation plein-bord testé, moins 10 cm bkfh = currentz - increment stophydroh = True MaxHydroH = max(HydroH, MaxHydroH) # stophydroh est vrai si un niveau plein-bord a été détecté if stophydroh: Result.setValue(currentrow,currentcol,bkfh) # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 if (direction == 4): currentrow = currentrow + 1 if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 if (direction == 16): currentcol = currentcol - 1 if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 if (direction == 64): currentrow = currentrow - 1 if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != -255): # Atteinte d'un confluent intheraster = False Result.save() return
def execute_Slope(r_dem, r_flowdir, str_frompoint, distancesmoothingpath, save_slope, save_newfp, messages, language="FR"): # Chargement des fichiers DEM = RasterIO(r_dem) FlowDir = RasterIO(r_flowdir) try: DEM.checkMatch(FlowDir) except Exception as e: messages.addErrorMessage(e.message) Result = RasterIO(r_flowdir, save_slope, float, -255) # Liste des nouveaux points de départ listfirstpoints = [] # Décompte du nombre de points de départ pour configurer de la barre de progression frompointcursor = arcpy.da.SearchCursor(str_frompoint, "OID@") count = 0 for frompoint in frompointcursor: count += 1 progtext = "Calcul des pentes" if language == "EN": progtext = "Processing" arcpy.SetProgressor("step", progtext, 0, count, 1) progres = 0 # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoint, "SHAPE@") for frompoint in frompointcursor: # Mise à jour de la barre de progression arcpy.SetProgressorPosition(progres) progres += 1 # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[0].firstPoint # Conversion des coordonnées currentcol = FlowDir.XtoCol(frompointshape.X) currentrow = FlowDir.YtoRow(frompointshape.Y) intheraster = True # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters if currentcol < 0 or currentcol >= FlowDir.raster.width or currentrow < 0 or currentrow >= FlowDir.raster.height: intheraster = False elif (FlowDir.getValue(currentrow, currentcol) != 1 and FlowDir.getValue(currentrow, currentcol) != 2 and FlowDir.getValue(currentrow, currentcol) != 4 and FlowDir.getValue(currentrow, currentcol) != 8 and FlowDir.getValue(currentrow, currentcol) != 16 and FlowDir.getValue(currentrow, currentcol) != 32 and FlowDir.getValue(currentrow, currentcol) != 64 and FlowDir.getValue(currentrow, currentcol) != 128): intheraster = False listpointsflowpath = [] totaldistance = 0 currentdistance = 0 confluencedist = 0 firstpoint = True # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): # On met à jour la liste des points le long de l'écoulement currentpoint = pointflowpath() currentpoint.row = currentrow currentpoint.col = currentcol currentpoint.addeddistance = currentdistance totaldistance = totaldistance + currentdistance currentpoint.distance = totaldistance listpointsflowpath.append(currentpoint) # les points sont mis à -999 (cela permet la détection des confluences) if confluencedist == 0: Result.setValue(currentrow, currentcol, -999) # On cherche le prochain point à partir du flow direction direction = FlowDir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 currentdistance = FlowDir.raster.meanCellWidth if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 currentdistance = math.sqrt(FlowDir.raster.meanCellWidth * FlowDir.raster.meanCellWidth + FlowDir.raster.meanCellHeight * FlowDir.raster.meanCellHeight) if (direction == 4): currentrow = currentrow + 1 currentdistance = FlowDir.raster.meanCellHeight if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 currentdistance = math.sqrt(FlowDir.raster.meanCellWidth * FlowDir.raster.meanCellWidth + FlowDir.raster.meanCellHeight * FlowDir.raster.meanCellHeight) if (direction == 16): currentcol = currentcol - 1 currentdistance = FlowDir.raster.meanCellWidth if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 currentdistance = math.sqrt(FlowDir.raster.meanCellWidth * FlowDir.raster.meanCellWidth + FlowDir.raster.meanCellHeight * FlowDir.raster.meanCellHeight) if (direction == 64): currentrow = currentrow - 1 currentdistance = FlowDir.raster.meanCellHeight if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 currentdistance = math.sqrt(FlowDir.raster.meanCellWidth * FlowDir.raster.meanCellWidth + FlowDir.raster.meanCellHeight * FlowDir.raster.meanCellHeight) # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= FlowDir.raster.width or currentrow < 0 or currentrow >= FlowDir.raster.height: intheraster = False elif (FlowDir.getValue(currentrow, currentcol) != 1 and FlowDir.getValue(currentrow, currentcol) != 2 and FlowDir.getValue(currentrow, currentcol) != 4 and FlowDir.getValue(currentrow, currentcol) != 8 and FlowDir.getValue(currentrow, currentcol) != 16 and FlowDir.getValue(currentrow, currentcol) != 32 and FlowDir.getValue(currentrow, currentcol) != 64 and FlowDir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != -255): # Atteinte d'un confluent if confluencedist == 0: confluencedist = totaldistance + currentdistance # On continue encore sur la distance de calcul de la pente après le confluent if (totaldistance + currentdistance - confluencedist) > distancesmoothingpath: intheraster = False currentpointnumber = 0 # Pour chaque point le long de l'écoulement while (currentpointnumber < len(listpointsflowpath)): currentpoint = listpointsflowpath[currentpointnumber] listpointforregression = [] listpointforregression.append(currentpoint) distancefromcurrentpoint = 0 nbcellsfromcurrentpoint = 0 try: # on s'éloigne du point courant, en allant vers l'amont, jusqu'à dépasser la distance de calcul de la pente while (distancefromcurrentpoint <= distancesmoothingpath / 2): nbcellsfromcurrentpoint = nbcellsfromcurrentpoint - 1 if (currentpointnumber + nbcellsfromcurrentpoint >= 0): # on mets à jour la distance jusqu'au point courant distancefromcurrentpoint = distancefromcurrentpoint + listpointsflowpath[ currentpointnumber + nbcellsfromcurrentpoint].addeddistance # on ajoute le point aux points à utiliser pour la régression (calcul de la pente au point courant) listpointforregression.append( listpointsflowpath[currentpointnumber + nbcellsfromcurrentpoint]) else: # la distance à l'extrémité amont est plus petie que la distance de calcul de pente raise IndexError distancefromcurrentpoint = 0 nbcellsfromcurrentpoint = 0 # même chose en s'éliognant du point courant vers l'aval while (distancefromcurrentpoint < distancesmoothingpath / 2): nbcellsfromcurrentpoint = nbcellsfromcurrentpoint + 1 if (currentpointnumber + nbcellsfromcurrentpoint < len(listpointsflowpath)): distancefromcurrentpoint = distancefromcurrentpoint + listpointsflowpath[ currentpointnumber + nbcellsfromcurrentpoint].addeddistance listpointforregression.append( listpointsflowpath[currentpointnumber + nbcellsfromcurrentpoint]) else: # la distance à l'extrémité aval est plus petite que la distance de calcul de pente raise IndexError # Calcul de la régression linéaire sumdistance = 0 sumelevation = 0 sumdistanceelevation = 0 sumsquaredistance = 0 for pointforregression in listpointforregression: sumdistance = sumdistance + pointforregression.distance sumelevation = sumelevation + DEM.getValue( pointforregression.row, pointforregression.col) sumdistanceelevation = sumdistanceelevation + pointforregression.distance * \ DEM.getValue(pointforregression.row, pointforregression.col) sumsquaredistance = sumsquaredistance + pointforregression.distance * pointforregression.distance slope = -(len(listpointforregression) * sumdistanceelevation - sumdistance * sumelevation) / ( len(listpointforregression) * sumsquaredistance - sumdistance * sumdistance) Result.setValue(currentpoint.row, currentpoint.col, slope) if firstpoint: # S'il s'agit du premier point (pour ce point de départ) pour lequel une valeur de pente est calculée, on enregistre ce point dans la liste des points de départ des pentes newpoint = arcpy.Point( FlowDir.raster.extent.XMin + (currentpoint.col + 0.5) * FlowDir.raster.meanCellWidth, FlowDir.raster.extent.YMax - (currentpoint.row + 0.5) * FlowDir.raster.meanCellHeight) listfirstpoints.append(newpoint) firstpoint = False except IndexError: # pas de calcul de la pente pour les extrémité amont et aval (il n'y a pas la distance suffisante pour le calcul de la pente) pass currentpointnumber = currentpointnumber + 1 Result.save() # On supprime les -999 du résultat final raster_res = arcpy.sa.SetNull(save_slope, save_slope, "VALUE = -999") raster_res.save(save_slope) # on enregistre la liste des points de départ des pente arcpy.CreateFeatureclass_management(os.path.dirname(save_newfp), os.path.basename(save_newfp), "POINT", spatial_reference=r_flowdir) pointcursor = arcpy.da.InsertCursor(save_newfp, "SHAPE@XY") for point in listfirstpoints: pointcursor.insertRow([(point.X, point.Y)]) return
def execute_D8toD4(r_flowdir, r_dem, str_frompoint, str_result, messages, language="FR"): """The source code of the tool.""" # Chargement des fichiers flowdir = RasterIO(r_flowdir) dem = RasterIO(r_dem) try: dem.checkMatch(flowdir) except Exception as e: messages.addErrorMessage(e.message) Result = RasterIO(r_flowdir, str_result, float, -255) donepoints = __Frompoint_paths() # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoint, ["SHAPE@", "OID@"]) for frompoint in frompointcursor: # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[0].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) intheraster = True # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): # On regarde la valeur du "flow direction" direction = flowdir.getValue(currentrow, currentcol) donepoints.add_point(currentrow, currentcol, frompoint[1]) # Si cette valeur est 1, 4, 16 ou 64, on se déplace sur des cases adjacentes. On garde la valeur. # Si cette valeur est 2, 8, 32 ou 128, on se déplace en diagonale. Un traitement est nécesaire. if (direction == 1): Result.setValue(currentrow, currentcol, direction) currentcol = currentcol + 1 if (direction == 2): # on regarde, parmi les deux cellules adjacentes pouvant remplacer le déplacement en diagonale, quelle est celle d'élévation la plus basse, et on passe par celle-ci # exemple : direction = 2 -> on se déplace en diagonale, en bas à droite # on peut donc remplacer ce déplacement par aller à droite (flow direction = 1) puis aller en bas (flow direction = 4) ou bien aller en bas puis aller à droite if dem.getValue(currentrow, currentcol + 1) is None: Result.setValue(currentrow, currentcol, 1) intheraster = False elif dem.getValue(currentrow + 1, currentcol) is None: Result.setValue(currentrow, currentcol, 4) intheraster = False elif dem.getValue(currentrow, currentcol + 1) < dem.getValue( currentrow + 1, currentcol): # La cellule à droite à une élévation plus basse que la cellule en bas, on choisie donc d'aller à droite puis ensuite en bas # On modifie donc le flow direction pour aller à droite Result.setValue(currentrow, currentcol, 1) # Puis on modifie le flow direction du la cellule à droite pour aller en bas if donepoints.done_previously(currentrow, currentcol + 1, frompoint[1]): # Atteinte d'un confluent intheraster = False else: Result.setValue(currentrow, currentcol + 1, 4) donepoints.add_point(currentrow, currentcol + 1, frompoint[1]) else: Result.setValue(currentrow, currentcol, 4) if donepoints.done_previously(currentrow + 1, currentcol, frompoint[1]): # Atteinte d'un confluent intheraster = False else: Result.setValue(currentrow + 1, currentcol, 1) donepoints.add_point(currentrow + 1, currentcol, frompoint[1]) currentcol = currentcol + 1 currentrow = currentrow + 1 if (direction == 4): Result.setValue(currentrow, currentcol, direction) currentrow = currentrow + 1 if (direction == 8): if dem.getValue(currentrow + 1, currentcol) is None: Result.setValue(currentrow, currentcol, 4) intheraster = False elif dem.getValue(currentrow, currentcol - 1) is None: Result.setValue(currentrow, currentcol, 16) intheraster = False elif dem.getValue(currentrow + 1, currentcol) < dem.getValue( currentrow, currentcol - 1): Result.setValue(currentrow, currentcol, 4) if donepoints.done_previously(currentrow + 1, currentcol, frompoint[1]): # Atteinte d'un confluent intheraster = False else: Result.setValue(currentrow + 1, currentcol, 16) donepoints.add_point(currentrow + 1, currentcol, frompoint[1]) else: Result.setValue(currentrow, currentcol, 16) if donepoints.done_previously(currentrow, currentcol - 1, frompoint[1]): # Atteinte d'un confluent intheraster = False else: Result.setValue(currentrow, currentcol - 1, 4) donepoints.add_point(currentrow, currentcol - 1, frompoint[1]) currentcol = currentcol - 1 currentrow = currentrow + 1 if (direction == 16): Result.setValue(currentrow, currentcol, direction) currentcol = currentcol - 1 if (direction == 32): if dem.getValue(currentrow - 1, currentcol) is None: Result.setValue(currentrow, currentcol, 64) intheraster = False elif dem.getValue(currentrow, currentcol - 1) is None: Result.setValue(currentrow, currentcol, 16) intheraster = False elif dem.getValue(currentrow - 1, currentcol) < dem.getValue( currentrow, currentcol - 1): Result.setValue(currentrow, currentcol, 64) if donepoints.done_previously(currentrow - 1, currentcol, frompoint[1]): # Atteinte d'un confluent intheraster = False else: Result.setValue(currentrow - 1, currentcol, 16) donepoints.add_point(currentrow - 1, currentcol, frompoint[1]) else: Result.setValue(currentrow, currentcol, 16) if donepoints.done_previously(currentrow, currentcol - 1, frompoint[1]): # Atteinte d'un confluent intheraster = False else: Result.setValue(currentrow, currentcol - 1, 64) donepoints.add_point(currentrow, currentcol - 1, frompoint[1]) currentcol = currentcol - 1 currentrow = currentrow - 1 if (direction == 64): Result.setValue(currentrow, currentcol, direction) currentrow = currentrow - 1 if (direction == 128): if dem.getValue(currentrow - 1, currentcol) is None: Result.setValue(currentrow, currentcol, 64) intheraster = False elif dem.getValue(currentrow, currentcol + 1) is None: Result.setValue(currentrow, currentcol, 1) intheraster = False elif dem.getValue(currentrow - 1, currentcol) < dem.getValue( currentrow, currentcol + 1): Result.setValue(currentrow, currentcol, 64) if donepoints.done_previously(currentrow - 1, currentcol, frompoint[1]): # Atteinte d'un confluent intheraster = False else: Result.setValue(currentrow - 1, currentcol, 1) donepoints.add_point(currentrow - 1, currentcol, frompoint[1]) else: Result.setValue(currentrow, currentcol, 1) if donepoints.done_previously(currentrow, currentcol + 1, frompoint[1]): # Atteinte d'un confluent intheraster = False else: Result.setValue(currentrow, currentcol + 1, 64) donepoints.add_point(currentrow, currentcol + 1, frompoint[1]) currentcol = currentcol + 1 currentrow = currentrow - 1 if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if donepoints.done_previously(currentrow, currentcol, frompoint[1]): # Atteinte d'un confluent intheraster = False Result.save() return
def execute_FlowLength(r_flowdir, str_frompoint, str_result, riverline, messages, language="FR"): """The source code of the tool.""" flowdir = RasterIO(r_flowdir) Result = RasterIO(r_flowdir, str_result, float, -255) frompointcursor = arcpy.da.SearchCursor(str_frompoint, "SHAPE@") for frompoint in frompointcursor: frompointshape = frompoint[0].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) intheraster = True if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False totaldistance = 0 currentdistance = 0 while (intheraster): totaldistance = totaldistance + currentdistance Result.setValue(currentrow, currentcol, totaldistance) # looking for the next point direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 4): currentrow = currentrow + 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 16): currentcol = currentcol - 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 64): currentrow = currentrow - 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != Result.nodata): # Atteinte d'une confluence intheraster = False Result.save() if riverline is not None: r_rivers = arcpy.sa.SetNull(arcpy.sa.IsNull(Result.raster), 1, "VALUE = 1") arcpy.RasterToPolyline_conversion(r_rivers, riverline) return
def execute_CS(r_flowdir, str_frompoints, distance, str_cs, messages, language = "FR"): # Chargement des fichiers flowdir = RasterIO(r_flowdir) # Fichier temporaire créé dans le "Scratch folder" temp_cs = arcpy.CreateScratchName("temp_cs", data_type="RasterDataset", workspace=arcpy.env.scratchFolder) Result = RasterIO(r_flowdir, temp_cs, float, -255) # Décompte du nombre de points de départ pour configurer de la barre de progression frompointcursor = arcpy.da.SearchCursor(str_frompoints, "OID@") count = 0 for frompoint in frompointcursor: count += 1 progtext = "Calcul de l'emplacement des sections transversales" if language == "EN": progtext = "Placing cross-sections" arcpy.SetProgressor("step", progtext, 0, count, 1) progres = 0 # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoints, "SHAPE@") for frompoint in frompointcursor: # Mise à jour de la barre de progression arcpy.SetProgressorPosition(progres) progres += 1 # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[0].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters intheraster = True if currentcol<0 or currentcol>=flowdir.raster.width or currentrow<0 or currentrow>= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False totaldistance = 0 currentdistance = 0 lastpointdistance = 0 # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): totaldistance = totaldistance + currentdistance # Entre deux sections transversales, les points sont mis à -999 (cela permet la détection des confluences) if totaldistance <= lastpointdistance + distance: Result.setValue(currentrow, currentcol, -999) else: Result.setValue(currentrow, currentcol, 1) lastpointdistance = totaldistance # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 currentdistance = math.sqrt( flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 4): currentrow = currentrow + 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 currentdistance = math.sqrt( flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 16): currentcol = currentcol - 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 currentdistance = math.sqrt( flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 64): currentrow = currentrow - 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 currentdistance = math.sqrt( flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != -255): # Atteinte d'un confluent intheraster = False # On supprime les -999 du résultat final Result.save() raster_res = arcpy.sa.SetNull(temp_cs, temp_cs, "VALUE = -999") # randomname = binascii.hexlify(os.urandom(6)) # temp_cs2 = arcpy.env.scratchWorkspace + "\\" + randomname # raster_res.save(temp_cs2) arcpy.RasterToPoint_conversion(raster_res, str_cs) arcpy.Delete_management(temp_cs) #arcpy.Delete_management(temp_cs2) return
def execute_WSsmoothing(r_flowdir, str_frompoint, r_z, r_zerr, str_zwssm, smooth_perc=0.9): flowdir = RasterIO(r_flowdir) z = RasterIO(r_z) zerr = RasterIO(r_zerr) zwssm = RasterIO(r_flowdir, str_zwssm, float, -255) trees = build_trees(flowdir, str_frompoint, zerr=zerr, ztosmooth=z) for tree in trees: for segment, prev_cs, cs in tree.browsepts(): if prev_cs != None: cs.z_fill = max(prev_cs.z_fill, cs.zerr) else: cs.z_fill = cs.zerr # z_breach à None permet le bon breach pour les parties parcourues plusieurs fois cs.z_breach = None # up to down for segment, prev_cs, cs in tree.uptodown_browsepts(): if prev_cs != None: if cs.z_breach != None: cs.z_breach = min(prev_cs.z_breach, cs.zerr, cs.z_breach) else: cs.z_breach = min(prev_cs.z_breach, cs.zerr) else: cs.z_breach = cs.zerr # indépendance par rapport à la résolution: # La méthode de base pondère le résultat final en fonction de la valeur au point et de la valeur précédente # (majorée/minorée par le fill ou le breach). L'indépendance par rapport à la résolution est faire en corrigeant # le poid par la puissance du ratio des distances. Le poid de base était pensé pour une résolution de 10m. # Ex : Résolution de 2m. On parcourt 5 pixels pour l'équivalent de un pixel à 10m. Si le poid est de 0.9 # pour 10m), z = 0.9z, dans le cas d'une chute à 0 (profil en forme de marche), il faut à 2m de résolution # z*poid^5 pour avoir l'équivalent, donc poid^5=0.9, donc poid=0.9^(1/5) # down to up for segment, prev_cs, cs in tree.browsepts(): if prev_cs != None: #cs.zsmooth2 = (1-smooth_perc**(cs.dist/10.))*cs.ztosmooth + smooth_perc**(cs.dist/10.)*max(prev_cs.zsmooth2, cs.z_breach) cs.zsmooth2 = max( ((1 - smooth_perc**(cs.dist / 10.)) * cs.ztosmooth + smooth_perc**(cs.dist / 10.) * prev_cs.zsmooth2), cs.z_breach) else: cs.zsmooth2 = cs.ztosmooth # up to down for segment, prev_cs, cs in tree.uptodown_browsepts(): if prev_cs != None: if hasattr(cs, "zsmooth1"): #cs.zsmooth1 = min((1 - smooth_perc**(cs.dist/10.)) * cs.ztosmooth + smooth_perc**(cs.dist/10.) * min(prev_cs.zsmooth1, cs.z_fill), cs.zsmooth1) cs.zsmooth1 = min( ((1 - smooth_perc**(cs.dist / 10.)) * cs.ztosmooth + smooth_perc**(cs.dist / 10.) * prev_cs.zsmooth1), cs.z_fill, cs.zsmooth1) else: #cs.zsmooth1 = (1-smooth_perc**(cs.dist/10.))*cs.ztosmooth + smooth_perc**(cs.dist/10.)*min(prev_cs.zsmooth1, cs.z_fill) cs.zsmooth1 = min( ((1 - smooth_perc**(cs.dist / 10.)) * cs.ztosmooth + smooth_perc**(cs.dist / 10.) * prev_cs.zsmooth1), cs.z_fill) else: cs.zsmooth1 = cs.ztosmooth cs.zsmooth = (cs.zsmooth1 + cs.zsmooth2) / 2 for segment in tree.treesegments(): for pt in segment.get_profile(): zwssm.setValue(pt.row, pt.col, pt.zsmooth) zwssm.save() return
def execute_RiverWith(r_binary, r_flowdir, str_frompoints, r_cs, oriented, str_width, messages, language="FR"): # Chargement des fichiers binary = RasterIO(r_binary) flowdir = RasterIO(r_flowdir) cs = RasterIO(r_cs) try: flowdir.checkMatch(cs) except Exception as e: messages.addErrorMessage(e.message) Result = RasterIO(r_flowdir, str_width, float, -255) # Décompte du nombre de points de départ pour configurer de la barre de progression frompointcursor = arcpy.da.SearchCursor(str_frompoints, "OID@") count = 0 for frompoint in frompointcursor: count += 1 progtext = "Calcul de la largeur aux sections transversales" if language == "EN": progtext = "Processing" arcpy.SetProgressor("step", progtext, 0, count, 1) progres = 0 # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoints, "SHAPE@") for frompoint in frompointcursor: # Mise à jour de la barre de progression arcpy.SetProgressorPosition(progres) progres += 1 # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[0].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) intheraster = True # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): # On se reprojète dans le système de coordonnées du raster binary colbinary = binary.XtoCol(flowdir.ColtoX(currentcol)) rowbinary = binary.YtoRow(flowdir.RowtoY(currentrow)) angle = cs.getValue(currentrow, currentcol) if angle != cs.nodata: if oriented: # calcul de la ligne et de la colonne du prochain point dans l'axe de la section transversale if (angle > math.pi / 4 and angle < 3 * math.pi / 4): rowinc = -1 colinc = math.cos(angle) else: colinc = 1 rowinc = -math.sin(angle) if angle > 3 * math.pi / 4: rowinc = -rowinc step = 0 while binary.getValue( rowbinary + int(rowinc * step), colbinary + int(colinc * step)) != binary.nodata: step += 1 # on répète les opérations précédentes en progressant dans l'autre sens le long de la section transversale step2 = 0 while binary.getValue( rowbinary - int(rowinc * step2), colbinary - int(colinc * step2)) != binary.nodata: step2 += 1 # if the process was not interrupted because an edge was reached if (rowbinary + int(rowinc * step)) >= 0 and ( colbinary + int(colinc * step) ) >= 0 and (rowbinary - int(rowinc * step2)) >= 0 and ( colbinary - int(colinc * step2) ) and (rowbinary + int(rowinc * step) ) < binary.raster.height and (colbinary + int( colinc * step)) < binary.raster.width and ( rowbinary - int(rowinc * step2) ) < binary.raster.height and (colbinary - int( colinc * step2)) < binary.raster.width: basedist = math.sqrt( (rowinc * binary.raster.meanCellHeight)**2 + (colinc * binary.raster.meanCellWidth)**2) width = basedist * (step + step2) Result.setValue(currentrow, currentcol, width) else: # on teste la largeur sur une étoile à 16 branches et on prend le minimum minwidth = None for star_i in range(1, 9): step = 0 step2 = 0 if star_i == 1: rowinc = 0 colinc = 1 if star_i == 2: rowinc = step % 2 colinc = 1 if star_i == 3: rowinc = 1 colinc = 1 if star_i == 4: rowinc = 1 colinc = step % 2 if star_i == 5: rowinc = 1 colinc = 0 if star_i == 6: rowinc = 1 colinc = -step % 2 if star_i == 7: rowinc = 1 colinc = -1 if star_i == 8: rowinc = step % 2 colinc = -1 while binary.getValue( rowbinary + int(rowinc * step), colbinary + int(colinc * step)) != binary.nodata: step += 1 while binary.getValue( rowbinary - int(rowinc * step2), colbinary - int(colinc * step2)) != binary.nodata: step2 += 1 width = None # if the process was not interrupted because an edge was reached if (rowbinary + int(rowinc * step)) >= 0 and ( colbinary + int(colinc * step) ) >= 0 and (rowbinary - int(rowinc * step2)) >= 0 and ( colbinary - int(colinc * step2) ) and (rowbinary + int(rowinc * step)) < binary.raster.height and ( colbinary + int(colinc * step) ) < binary.raster.width and ( rowbinary - int(rowinc * step2) ) < binary.raster.height and (colbinary - int( colinc * step2)) < binary.raster.width: basedist = math.sqrt( (rowinc * binary.raster.meanCellHeight)**2 + (colinc * binary.raster.meanCellWidth)**2) width = basedist * (step + step2) if minwidth is not None: if width is not None: minwidth = min(minwidth, width) else: minwidth = width if minwidth is not None: Result.setValue(currentrow, currentcol, minwidth) # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 if (direction == 4): currentrow = currentrow + 1 if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 if (direction == 16): currentcol = currentcol - 1 if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 if (direction == 64): currentrow = currentrow - 1 if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != -255): # Atteinte d'un confluent intheraster = False Result.save() return
def execute_Breach(r_dem, r_flowdir, str_frompoint, SaveResult, messages, language="FR"): # Chargement des fichiers dem = RasterIO(r_dem) flowdir = RasterIO(r_flowdir) try: dem.checkMatch(flowdir) except Exception as e: messages.addErrorMessage(str(e)) Result = RasterIO(r_flowdir, SaveResult, float, -255) # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoint, "SHAPE@") for frompoint in frompointcursor: # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[0].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) # prev_z : élévation au point précédent (= élévation du point testé pour le premier point) prev_z = dem.getValue(currentrow, currentcol) # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters intheraster = True if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if dem.getValue(currentrow, currentcol) == dem.nodata: intheraster = False confluence = False # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): if not confluence: # L'élévation finale du point testé (z) est la valeur la plus petite entre son élévation actuelle et l'élévation du point précédent (prev_z) newz = dem.getValue(currentrow, currentcol) else: # Si on a atteint une confluence, on continue jusqu'à ce que qu'on atteingne un point plus bas newz = Result.getValue(currentrow, currentcol) if newz <= prev_z: intheraster = False z = min(prev_z, newz) Result.setValue(currentrow, currentcol, z) prev_z = z # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 if (direction == 4): currentrow = currentrow + 1 if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 if (direction == 16): currentcol = currentcol - 1 if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 if (direction == 64): currentrow = currentrow - 1 if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if dem.getValue(currentrow, currentcol) == dem.nodata: intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != -255): # Atteinte d'un confluent confluence = True Result.save() return
def execute_CreateZone(r_flowdir, str_lakes, r_slope, minslope, str_frompoint, distance, bufferw, str_zonesfolder, messages): str_segments = str_zonesfolder + "\\segments" str_linesegments = str_zonesfolder + "\\line_segments.shp" str_bufferedsegments = str_zonesfolder + "\\buff_segments.shp" save_sourcepoints = str_zonesfolder + "\\sourcepoints.shp" str_r_lakes = str_zonesfolder + "\\r_lakes" flowdir = RasterIO(r_flowdir) if r_slope is not None: slope = RasterIO(r_slope) try: flowdir.checkMatch(slope) except Exception as e: messages.addErrorMessage(e.message) else: slope = None # Conversion des lacs en raster et copie arcpy.env.snapRaster = flowdir.raster arcpy.env.outputCoordinateSystem = flowdir.raster.spatialReference arcpy.env.extent = flowdir.raster arcpy.PolygonToRaster_conversion(str_lakes, arcpy.Describe(str_lakes).OIDFieldName, str_r_lakes, cellsize=flowdir.raster) lakes = RasterIO(arcpy.Raster(str_r_lakes)) arcpy.CopyFeatures_management(str_lakes, str_zonesfolder + "\\lakes.shp") str_lakes = str_zonesfolder + "\\lakes.shp" arcpy.AddGeometryAttributes_management(str_lakes, "EXTENT") ### Début du traitement perrmettant d'identifier les segments (sous forme de raster) ### raster_segments = RasterIO(r_flowdir, str_segments, int, -255) # numérotation des segments segnumber = 0 lakes_bci = {} toclip = {} inputpoints = {} # Pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoint, ["SHAPE@", "OID@"]) for frompoint in frompointcursor: # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[0].firstPoint # Nouvelle rivière : on change de segment segnumber += 1 # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters intheraster = True if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False listpointsflowpath = [] totaldistance = 0 currentdistance = 0 inlake = True # True si la rivière (depuis le point de départ jusqu'au confluent) est composée d'au moins deux segments dividedriver = False # listtomerged contient la liste des segments trop courts, qui doivent être fusionnés avec segment précédent listtomerged = [] # Pour chaque cellule en suivant l'écoulement while (intheraster): waslake = inlake inlake = False lakevalue = lakes.getValue(currentrow, currentcol) inlake = (lakevalue != lakes.nodata) if not (inlake and waslake): # Distance parcourue depuis le début du segment totaldistance = totaldistance + currentdistance slope_criteria = True if slope is not None: slope_criteria = slope.getValue(currentrow, currentcol) > minslope # Test si on arrive à un lac if inlake and not waslake: # Segment trop court si de longueur inférieure à 30% de la distance voullue # Le segment doit être alors fusionné avec le segment précédent (qui existe uniquement si dividedriver = True) # ajout de l'info de clipper ensuite également coordX = flowdir.ColtoX(currentcol) coordY = flowdir.RowtoY(currentrow) fieldidlakes = arcpy.Describe(str_lakes).OIDFieldName shplakes = arcpy.da.SearchCursor(str_lakes, [ "SHAPE@", "EXT_MIN_X", "EXT_MAX_X", "EXT_MIN_Y", "EXT_MAX_Y", fieldidlakes ]) for shplake in shplakes: if shplake[0].contains(arcpy.Point(coordX, coordY)): lakes_bci[segnumber] = shplakes[5] distXmin = abs(coordX - shplake[1]) distXmax = abs(coordX - shplake[2]) distYmin = abs(coordY - shplake[3]) distYmax = abs(coordY - shplake[4]) mini = min(distXmin, distXmax, distYmin, distYmax) if mini == distXmin: toclip[segnumber] = ["Xmax", shplake[1]] messages.addMessage( str(segnumber) + " Xmax " + str(shplake[1])) if mini == distXmax: toclip[segnumber] = ["Xmin", shplake[2]] messages.addMessage( str(segnumber) + " Xmin " + str(shplake[2])) if mini == distYmin: toclip[segnumber] = ["Ymax", shplake[3]] messages.addMessage( str(segnumber) + " Ymax " + str(shplake[3])) if mini == distYmax: toclip[segnumber] = ["Ymin", shplake[4]] messages.addMessage( str(segnumber) + " Ymin " + str(shplake[4])) if totaldistance < 0.3 * distance and dividedriver: if segnumber in toclip: toclip[segnumber - 1] = toclip.pop(segnumber) listtomerged.append(segnumber) totaldistance = 0 segnumber += 1 dividedriver = False elif totaldistance > distance and slope_criteria: # Test si on a parcouru la distance voullue totaldistance = 0 segnumber += 1 dividedriver = True if not inlake: # On conseerve une liste des points traités, avec leur numéro de segment currentpoint = pointflowpath() currentpoint.row = currentrow currentpoint.col = currentcol currentpoint.X = flowdir.ColtoX(currentcol) currentpoint.Y = flowdir.RowtoY(currentrow) currentpoint.distance = totaldistance currentpoint.segnumber = segnumber currentpoint.frompointid = frompoint[1] listpointsflowpath.append(currentpoint) # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 4): currentrow = currentrow + 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 16): currentcol = currentcol - 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 64): currentrow = currentrow - 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: confluence_seg = raster_segments.getValue( currentrow, currentcol) if (confluence_seg != -255): # Atteinte d'un confluent déjà traité # Si le segment dans lequel on arrive est limité par un lac, le confluent peut l'être aussi # On copie l'item toclip pour limiter l'étendu de la zone # par contre on garde l'élévation à -999 (hfix sera le résultat de la simulation du cours d'eau confluent) if confluence_seg in listtomerged: confluence_seg -= 1 if confluence_seg in toclip: clipitem = list(toclip[confluence_seg]) toclip[segnumber] = clipitem if totaldistance < 0.3 * distance and dividedriver: # Segment trop court si de longueur inférieure à 30% de la distance voullue # Le segment doit être alors fusionné avec le segment précédent (qui existe uniquement si dividedriver = True) listtomerged.append(segnumber) if segnumber in toclip: toclip[segnumber - 1] = toclip.pop(segnumber) intheraster = False # Pour chaque point traité le long de l'écoulement for currentpoint in listpointsflowpath: # Si c'est un point d'un segment trop court, on remplace le numéro du segment par le numéro du segment précédent if currentpoint.segnumber in listtomerged: currentpoint.segnumber -= 1 # On enregistre le point raster_segments.setValue(currentpoint.row, currentpoint.col, currentpoint.segnumber) if currentpoint.segnumber not in inputpoints: newpoint = pointflowpath() newpoint.type = "main" newpoint.frompointid = currentpoint.frompointid # Coordonnées du point source newpoint.X = currentpoint.X newpoint.Y = currentpoint.Y inputpoints[currentpoint.segnumber] = newpoint raster_segments.save() ### Fin du traitement perrmettant d'identifier les segments ### ### Transformation du raster des segments en zones #### # Transformation en polyline tmp_segments = arcpy.env.scratchWorkspace + "\\tmpsegments.shp" arcpy.RasterToPolyline_conversion(str_segments, tmp_segments) arcpy.Dissolve_management(tmp_segments, str_linesegments, "GRID_CODE") arcpy.Delete_management(tmp_segments) # Création de la zone tampon # Harcoded : buffer longitudinal de 1/10 de l'extension latérale (obtenue par Euclidienne Allocation) tmp_segmentsbuf = arcpy.env.scratchWorkspace + "\\tmpsegments_buf.shp" arcpy.Buffer_analysis(str_linesegments, tmp_segmentsbuf, bufferw / 10.) segalloc = arcpy.sa.EucAllocation(raster_segments.raster, bufferw) arcpy.RasterToPolygon_conversion(segalloc, tmp_segments) arcpy.AddField_management(tmp_segments, "GRID_CODE", "LONG") arcpy.CalculateField_management(tmp_segments, "GRID_CODE", "!GRIDCODE!", "PYTHON_9.3") tmp_segments2 = arcpy.env.scratchWorkspace + "\\tmpsegments2.shp" arcpy.Merge_management([tmp_segmentsbuf, tmp_segments], tmp_segments2) arcpy.Dissolve_management(tmp_segments2, str_bufferedsegments, ["GRID_CODE"], multi_part="SINGLE_PART") arcpy.Delete_management(tmp_segments) arcpy.Delete_management(tmp_segments2) arcpy.Delete_management(str_lakes) # Création de la zone pour chaque segment arcpy.CreateFeatureclass_management( str_zonesfolder, "polyzones.shp", "POLYGON", str_bufferedsegments, spatial_reference=flowdir.raster.spatialReference) polyzones = str_zonesfolder + "\\polyzones.shp" arcpy.AddField_management(polyzones, "Lake_ID", "LONG") cursor = arcpy.da.InsertCursor(polyzones, ["GRID_CODE", "SHAPE@", "Lake_ID"]) segmentscursor = arcpy.da.UpdateCursor(str_bufferedsegments, ["GRID_CODE", "SHAPE@"]) for segment in segmentscursor: Xmin = segment[1].extent.XMin Ymin = segment[1].extent.YMin Xmax = segment[1].extent.XMax Ymax = segment[1].extent.YMax if segment[0] in toclip: if toclip[segment[0]][0] == "Xmin": Xmin = max(toclip[segment[0]][1], Xmin) if toclip[segment[0]][0] == "Xmax": Xmax = min(toclip[segment[0]][1], Xmax) if toclip[segment[0]][0] == "Ymin": Ymin = max(toclip[segment[0]][1], Ymin) if toclip[segment[0]][0] == "Ymax": Ymax = min(toclip[segment[0]][1], Ymax) segmentscursor.updateRow(segment) array = arcpy.Array([ arcpy.Point(Xmin, Ymin), arcpy.Point(Xmin, Ymax), arcpy.Point(Xmax, Ymax), arcpy.Point(Xmax, Ymin) ]) polygon = arcpy.Polygon(array) if segment[0] in lakes_bci: lakeid = lakes_bci[segment[0]] else: lakeid = -999 cursor.insertRow([segment[0], polygon, lakeid]) del cursor del segmentscursor arcpy.CreateFeatureclass_management( os.path.dirname(save_sourcepoints), os.path.basename(save_sourcepoints), "POINT", spatial_reference=flowdir.raster.spatialReference) arcpy.AddField_management(save_sourcepoints, "ZoneID", "LONG") arcpy.AddField_management(save_sourcepoints, "fpid", "LONG") pointcursor = arcpy.da.InsertCursor(save_sourcepoints, ["ZoneID", "fpid", "SHAPE@XY"]) for pointkey in inputpoints: pointcursor.insertRow([ pointkey, inputpoints[pointkey].frompointid, (inputpoints[pointkey].X, inputpoints[pointkey].Y) ]) del pointcursor return
def execute_LinearInterpolationWithPriority(r_flowdir, str_frompoint, r_values, str_results, messages, language="FR"): # Chargement des fichiers flowdir = RasterIO(r_flowdir) valuesatcs = RasterIO(r_values) try: flowdir.checkMatch(valuesatcs) except Exception as e: messages.addErrorMessage(e.message) trees = build_trees(flowdir, str_frompoint, tointerpolate=valuesatcs) # Find how to interpolate # Interpolation can not be done in this first run through the trees because the totaldistance must be calculated first for tree in trees: totaldistance = 0 datacs_down = None for segment in tree.treesegments(): for cs in segment.get_profile(): if cs.tointerpolate != valuesatcs.nodata: datacs_down = cs bestcsup = None for datacs_up in tree.points_up_with_data( segment, cs, "tointerpolate", valuesatcs.nodata): if datacs_down is not None: # a downstream point exists: looking for the upstream point with the closest value if bestcsup is None or (abs(datacs_down.tointerpolate - datacs_up.tointerpolate) < abs(datacs_down.tointerpolate - bestcsup.tointerpolate)): bestcsup = datacs_up else: # a downstream point does not exist: looking for the upstream point with the highest value if bestcsup is None or (datacs_up.tointerpolate > bestcsup.tointerpolate): bestcsup = datacs_up cs.datacs_up = bestcsup if (datacs_down is not None) and (datacs_down.datacs_up == cs.datacs_up): # general case cs.datacs_down = datacs_down else: # special case at confluence, the local cs in a narrow steam, must be extrapolated from the upstream data # Or, the cs is downstream the most downstream data point cs.datacs_down = None totaldistance += cs.dist cs.totaldist = totaldistance # Calculating the interpolations and saving the results Result = RasterIO(r_values, str_results, float, -255) for tree in trees: for segment in tree.treesegments(): for cs in segment.get_profile(): if cs.datacs_down is None: # extrapolation from upstream cs.interpolated = cs.datacs_up.tointerpolate else: if cs.datacs_up is None: # extrapolation from downstream cs.interpolated = cs.datacs_down.tointerpolate else: # interpolation cs.interpolated = (cs.totaldist - cs.datacs_down.totaldist) \ * (cs.datacs_up.tointerpolate - cs.datacs_down.tointerpolate) \ / (cs.datacs_up.totaldist - cs.datacs_down.totaldist) \ + cs.datacs_down.tointerpolate Result.setValue(cs.row, cs.col, cs.interpolated) Result.save() return
def execute_GaussianSmooth(r_flowdir, str_frompoint, r_values, gaussiansigma, nbgaussianpoints, SaveResult, messages, language="FR"): # Chargement des fichiers flowdir = RasterIO(r_flowdir) valuesraster = RasterIO(r_values) try: flowdir.checkMatch(valuesraster) except Exception as e: messages.addErrorMessage(e.message) Result = RasterIO(r_flowdir, SaveResult, float, -255) # Décompte du nombre de points de départ pour configurer de la barre de progression count = 0 frompointcursor = arcpy.da.SearchCursor(str_frompoint, "OID@") for frompoint in frompointcursor: count += 1 progtext = "Lissage par moyenne mobile" if language == "EN": progtext = "Processing" arcpy.SetProgressor("step", progtext, 0, count, 1) progres = 0 # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoint, ["OID@", "SHAPE@"]) for frompoint in frompointcursor: # Mise à jour de la barre de progression arcpy.SetProgressorPosition(progres) progres += 1 # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[1].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) intheraster = True # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False listflowpath = [] listpointsflowpath = [] listdistance = [] listelevation = [] totaldistance = 0 currentdistance = 0 confluencedist = 0 # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): currentpoint = pointflowpath() currentpoint.row = currentrow currentpoint.col = currentcol listpointsflowpath.append(currentpoint) totaldistance = totaldistance + currentdistance listflowpath.append(totaldistance) # On crée une liste des points d'élévation connue le long de l'écoulement, ainsi qu'une liste associée avec leur distance depuis le point de distance if valuesraster.getValue(currentrow, currentcol) != valuesraster.nodata: listdistance.append(totaldistance) listelevation.append( valuesraster.getValue(currentrow, currentcol)) # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 4): currentrow = currentrow + 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 16): currentcol = currentcol - 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 64): currentrow = currentrow - 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 currentdistance = math.sqrt(flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != -255): # Atteinte d'un confluent if confluencedist == 0: confluencedist = totaldistance + currentdistance # On continue encore sur la distance d'extension après le confluent if (totaldistance + currentdistance - confluencedist) > nbgaussianpoints / 2: intheraster = False if len(listdistance) <= 1: # Avertissement si il n'y a qu'un seul (ou aucun) point de données if language == "FR": messages.addWarningMessage( "Point source {0}: pas assez de sections transversales". format(frompoint[0])) else: messages.addWarningMessage( "From point {0}: not enough cross-sections".format( frompoint[0])) else: currentpointnumber = 0 # Traitement pour chaque point le long de l'écoulement while (currentpointnumber < len(listflowpath)): currentpoint = listpointsflowpath[currentpointnumber] weights = [] values = [] sumwgt = 0 # On parcourt tous les points d'élévation connue for i in range(len(listdistance)): distlocale = abs(listdistance[i] - listflowpath[currentpointnumber]) # ... pour trouver ceux situés à l'intérieur de la fenêtre if distlocale < (nbgaussianpoints - 1) / 2: # On utilise alors la courbe gaussienne pour trouver la pondération de chaque point (et mettre à jour la somme des poids) pointwgt = 1 / (gaussiansigma * math.sqrt(2 * math.pi)) * math.exp( -0.5 * (distlocale / gaussiansigma)**2) sumwgt += pointwgt # Et on enregistre les valeurs dans des listes weights.append(pointwgt) values.append(listelevation[i]) # Message d'avertissement si la taille de fenêtre est insuffisante if len(weights) == 0: if language == "FR": messages.addWarningMessage( "Manque trop important de données à interpoler : " + str(frompoint[0]) + " - " + str(listflowpath[currentpointnumber])) else: messages.addWarningMessage( "Not enough data to interpolate : " + str(frompoint[0]) + " - " + str(listflowpath[currentpointnumber])) # On calcul la valeur finale à partir des valeurs et des poids associés finalvalue = 0 for i in range(len(weights)): finalvalue += values[i] * weights[i] / sumwgt Result.setValue(currentpoint.row, currentpoint.col, finalvalue) currentpointnumber = currentpointnumber + 1 Result.save() return
def execute_MovingWindowStats(r_flowdir, str_frompoint, r_values, distance, function, SaveResult, messages): # Chargement des fichiers flowdir = RasterIO(r_flowdir) valuesraster = RasterIO(r_values) try: flowdir.checkMatch(valuesraster) except Exception as e: messages.addErrorMessage(e.message) Result = RasterIO(r_flowdir, SaveResult, float,-255) # Décompte du nombre de points de départ pour configurer de la barre de progression count = 0 frompointcursor = arcpy.da.SearchCursor(str_frompoint, "OID@") for frompoint in frompointcursor: count += 1 arcpy.SetProgressor("step", "Lissage par moyenne mobile", 0, count, 1) progres = 0 # Traitement effectué pour chaque point de départ frompointcursor = arcpy.da.SearchCursor(str_frompoint, ["OID@", "SHAPE@"]) for frompoint in frompointcursor: # Mise à jour de la barre de progression arcpy.SetProgressorPosition(progres) progres += 1 # On prend l'objet géométrique (le point) associé à la ligne dans la table frompointshape = frompoint[1].firstPoint # Conversion des coordonnées currentcol = flowdir.XtoCol(frompointshape.X) currentrow = flowdir.YtoRow(frompointshape.Y) intheraster = True # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters if currentcol<0 or currentcol>=flowdir.raster.width or currentrow<0 or currentrow>= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False listflowpath = [] listpointsflowpath = [] listdistance = [] listelevation = [] totaldistance = 0 currentdistance = 0 # Traitement effectué sur chaque cellule le long de l'écoulement while (intheraster): currentpoint = pointflowpath() currentpoint.row = currentrow currentpoint.col = currentcol listpointsflowpath.append(currentpoint) totaldistance = totaldistance + currentdistance listflowpath.append(totaldistance) # On crée une liste des points d'élévation connue le long de l'écoulement, ainsi qu'une liste associée avec leur distance depuis le point de distance if valuesraster.getValue(currentrow, currentcol) != valuesraster.nodata: listdistance.append(totaldistance) listelevation.append(valuesraster.getValue(currentrow, currentcol)) # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 currentdistance = math.sqrt( flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 4): currentrow = currentrow + 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 currentdistance = math.sqrt( flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 16): currentcol = currentcol - 1 currentdistance = flowdir.raster.meanCellWidth if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 currentdistance = math.sqrt( flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) if (direction == 64): currentrow = currentrow - 1 currentdistance = flowdir.raster.meanCellHeight if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 currentdistance = math.sqrt( flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight) # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height: intheraster = False elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128): intheraster = False if intheraster: if (Result.getValue(currentrow, currentcol) != -255): intheraster = False if len(listdistance) <= 1: # Avertissement si il n'y a qu'un seul (ou aucun) point de données messages.addWarningMessage("Point source {0}: pas assez de sections transversales".format(frompoint[0])) else: currentpointnumber = 0 # Traitement pour chaque point le long de l'écoulement while (currentpointnumber < len(listflowpath)): currentpoint = listpointsflowpath[currentpointnumber] weights = [] values = [] sumwgt = 0 # On parcourt tous les points d'élévation connue for i in range(len(listdistance)): distlocale = abs(listdistance[i]-listflowpath[currentpointnumber]) # ... pour trouver ceux situés à l'intérieur de la fenêtre if distlocale <= distance / 2: values.append(listelevation[i]) # On calcul la valeur finale à partir des valeurs et des poids associés finalvalue = function(values) Result.setValue(currentpoint.row, currentpoint.col, finalvalue) currentpointnumber = currentpointnumber + 1 Result.save() return