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_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_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_RunSim_prev_2var(str_zonefolder, str_simfolder, str_lisfloodfolder, str_csvq, str_csvz, voutput, simtime, channelmanning, r_zbed, str_log, messages): str_inbci = str_zonefolder + "\\inbci.shp" str_outbci = str_zonefolder + "\\outbci.shp" zbed = RasterIO(r_zbed) bcipointcursor = arcpy.da.SearchCursor(str_inbci, ["SHAPE@", "zoneid", "flowacc", "type", "fpid"]) dictsegmentsin = {} for point in bcipointcursor: if point[1] not in dictsegmentsin: dictsegmentsin[point[1]] = [] dictsegmentsin[point[1]].append(point) allzones = list(dictsegmentsin.keys()) allzones.sort() dictzones_fp = {} for zone in allzones: if dictsegmentsin[zone][0][4] not in dictzones_fp: dictzones_fp[dictsegmentsin[zone][0][4]] = [] dictzones_fp[dictsegmentsin[zone][0][4]].append(zone) sortedzones = [] listfp = list(dictzones_fp.keys()) listfp.sort() for fp in listfp: listzones_fp = dictzones_fp[fp] listzones_fp.sort(reverse=True) sortedzones.extend(listzones_fp) # Ajout des information du fichier outbci.shp listzonesout = {} bcipointcursor = arcpy.da.SearchCursor(str_outbci, ["zoneid", "side", "lim1", "lim2", "side2", "lim3", "lim4", "SHAPE@"]) for point in bcipointcursor: listzonesout[point[0]] = point zones = str_zonefolder + "\\envelopezones.shp" # récupération du bci lac zonesscursor = arcpy.da.SearchCursor(zones, ["GRID_CODE", "SHAPE@", "Lake_ID"]) lakeid_byzone = {} for zoneshp in zonesscursor: if zoneshp[2] != -999: lakeid_byzone[zoneshp[0]] = zoneshp[2] filelog = open(str_log, 'w') csvfilez = open(str_csvz) csv_readerz = csv.DictReader(csvfilez) ref_raster = None for csvzrow in csv_readerz: zname = csvzrow["nom"] hfix = float(csvzrow["z"]) csvfileq = open(str_csvq) csv_readerq = csv.DictReader(csvfileq) for csvqrow in csv_readerq: simname = csvqrow["nom"] + "_" + zname currentsimfolder = str_simfolder + "\\" + simname currentresult = str_simfolder + "\\res_" + simname simq = float(csvqrow["q"]) if not os.path.isdir(currentsimfolder): os.makedirs(currentsimfolder) for zone in sortedzones: segment = dictsegmentsin[zone] for point in sorted(segment, key=lambda q: q[2]): if point[3]=="main": try: if not arcpy.Exists(currentsimfolder + "\\elev_zone" + str(point[1])): if ref_raster is None: ref_raster = arcpy.Raster(str_zonefolder + "\\zone" + str(point[1])) outpointshape = listzonesout[point[1]][7].firstPoint if arcpy.Exists(currentresult): # dans le cas où un fichier résultat existe avec un résulat valide, on prends les résultats de ce fichier comme limite aval if arcpy.Exists(currentsimfolder + "\\tmp_zone" + str(point[1])): arcpy.Delete_management(currentsimfolder + "\\tmp_zone" + str(point[1])) arcpy.Copy_management(currentresult, currentsimfolder + "\\tmp_zone" + str(point[1])) res_downstream = RasterIO(arcpy.Raster(currentsimfolder + "\\tmp_zone" + str(point[1]))) hfix_raster = res_downstream.getValue(res_downstream.YtoRow(outpointshape.Y), res_downstream.XtoCol(outpointshape.X)) if hfix_raster != res_downstream.nodata: hfix_sim = hfix_raster else: hfix_sim = hfix arcpy.Delete_management(currentsimfolder + "\\tmp_zone" + str(point[1])) else: hfix_sim = hfix # par newfile = str_simfolder + "\\zone" + str(point[1]) + ".par" if os.path.isfile(newfile): os.remove(newfile) filepar = open(newfile, 'w') filepar.write("DEMfile\tzone" + str(point[1]) + ".txt\n") filepar.write("resroot\tzone" + str(point[1]) + "\n") filepar.write("dirroot\t" + simname + "\n") filepar.write("manningfile\tnzone" + str(point[1]) + ".txt\n") filepar.write("bcifile\tzone" + str(point[1]) + ".bci" + "\n") filepar.write("sim_time\t" + str(simtime) + "\n") filepar.write("saveint\t" + str(simtime) + "\n") filepar.write("bdyfile\t"+ simname +"\\zone" + str(point[1]) + ".bdy" + "\n") filepar.write("SGCwidth\twzone" + str(point[1]) + ".txt\n") filepar.write("SGCbank\tzone" + str(point[1]) + ".txt\n") filepar.write("SGCbed\tdzone" + str(point[1]) + ".txt\n") filepar.write("SGCn\t" + str(channelmanning) + "\n") filepar.write("chanmask\tmzone" + str(point[1]) + ".txt\n") # Vitesses du courant if voutput: filepar.write("hazard\n") filepar.write("qoutput\n") filepar.write("cfl\t0.3\n") filepar.write("max_Froude\t1\n") # filepar.write("debug\n") filepar.close() # bdy newfilebdy = currentsimfolder + "\\zone" + str(point[1]) + ".bdy" for point2 in sorted(segment, key=lambda q: q[2]): q_value = point2[2]*simq*(ref_raster.meanCellHeight*ref_raster.meanCellWidth)/1000000. if point2[3] == "main": # Création du fichier bdy pointdischarge = q_value / ( (ref_raster.meanCellHeight + ref_raster.meanCellWidth) / 2) lastdischarge = q_value latnum = 0 filebdy = open(newfilebdy, 'w') filebdy.write("zone"+str(point[1]) + ".bdy\n") filebdy.write("zone"+str(point[1]) + "\n") filebdy.write("3\tseconds\n") filebdy.write("0\t0\n") filebdy.write("{0:.3f}".format(pointdischarge) + "\t50000\n") filebdy.write("{0:.3f}".format(pointdischarge) + "\t" + str(simtime)) filebdy.close() else: latnum += 1 pointdischarge = (q_value - lastdischarge) / ( (ref_raster.meanCellHeight + ref_raster.meanCellWidth) / 2) lastdischarge = q_value filebdy = open(newfilebdy, 'a') filebdy.write("\nzone" + str(point[1]) + "_" + str(latnum) + "\n") filebdy.write("3\tseconds\n") filebdy.write("0\t0\n") filebdy.write("{0:.3f}".format(pointdischarge) + "\t50000\n") filebdy.write("{0:.3f}".format(pointdischarge) + "\t" + str(simtime)) filebdy.close() # condition aval: 30cm au dessus du lit pour commencer zdep = min(zbed.getValue(zbed.YtoRow(outpointshape.Y), zbed.XtoCol(outpointshape.X)) + 0.3, hfix_sim) filebdy = open(newfilebdy, 'a') filebdy.write("\nhvar\n") filebdy.write("4\tseconds\n") filebdy.write("{0:.2f}".format(zdep) + "\t0\n") filebdy.write("{0:.2f}".format(zdep) + "\t50000\n") filebdy.write("{0:.2f}".format(hfix_sim) + "\t55000\n") filebdy.write("{0:.2f}".format(hfix_sim) + "\t" + str(simtime)) filebdy.close() # calcul pour le -steadytol # Divise le débit par 200 et ne conserve qu'un chiffre significatif steadytol = str( round(lastdischarge / 200., - int(math.floor(math.log10(abs(lastdischarge / 200.)))))) subprocess.check_call([str_lisfloodfolder + "\\lisflood_intelRelease_double.exe", "-steady", "-steadytol", steadytol, str_simfolder + "\\zone" + str(point[1]) + ".par"], shell=True, cwd=str_simfolder) # Conversion des fichiers output # on renomme les fichiers créés (nécessaire pour être acceptés par l'outil de convsersion ASCII vers raster) zonename = "zone"+str(point[1]) if os.path.exists(currentsimfolder + "\\" + zonename + "elev.txt"): os.remove(currentsimfolder + "\\" + zonename + "elev.txt") if os.path.exists(currentsimfolder + "\\" + zonename + "-9999.elev"): os.rename(currentsimfolder + "\\" + zonename + "-9999.elev", currentsimfolder + "\\" + zonename + "elev.txt") else: os.rename(currentsimfolder + "\\" + zonename + "-0001.elev", currentsimfolder + "\\" + zonename + "elev.txt") filelog.write("Steady state not reached : " + zonename + ", sim " + simname) messages.addWarningMessage("Steady state not reached : " + zonename + ", sim " + simname) if os.path.exists(currentsimfolder + "\\" + zonename + "-9999.Vx") or os.path.exists(currentsimfolder + "\\" + zonename + "-0001.Vx"): if os.path.exists(currentsimfolder + "\\" + zonename + "Vx.txt"): os.remove(currentsimfolder + "\\" + zonename + "Vx.txt") if os.path.exists(currentsimfolder + "\\" + zonename + "Vy.txt"): os.remove(currentsimfolder + "\\" + zonename + "Vy.txt") if os.path.exists(currentsimfolder + "\\" + zonename + "-9999.Vx"): os.rename(currentsimfolder + "\\" + zonename + "-9999.Vx", currentsimfolder+ "\\" + zonename + "Vx.txt") os.rename(currentsimfolder + "\\" + zonename + "-9999.Vy", currentsimfolder + "\\" + zonename + "Vy.txt") else: os.rename(currentsimfolder + "\\" + zonename + "-0001.Vx", currentsimfolder + "\\" + zonename + "Vx.txt") os.rename(currentsimfolder + "\\" + zonename + "-0001.Vy", currentsimfolder + "\\" + zonename + "Vy.txt") arcpy.ASCIIToRaster_conversion(currentsimfolder + "\\" + zonename + "Vx.txt", currentsimfolder + "\\Vx_" + zonename, "FLOAT") arcpy.ASCIIToRaster_conversion(currentsimfolder + "\\" + zonename + "Vy.txt", currentsimfolder + "\\Vy_" + zonename, "FLOAT") arcpy.DefineProjection_management(currentsimfolder + "\\Vx_" + zonename, ref_raster.spatialReference) arcpy.DefineProjection_management(currentsimfolder + "\\Vy_" + zonename, ref_raster.spatialReference) # Conversion des fichiers de sortie en raster pour ArcGIS str_elev = currentsimfolder + "\\elev_" + zonename arcpy.ASCIIToRaster_conversion(currentsimfolder + "\\" + zonename + "elev.txt", str_elev, "FLOAT") # Ajout de la projection arcpy.DefineProjection_management(str_elev, ref_raster.spatialReference) if not arcpy.Exists(currentresult): arcpy.Copy_management(currentsimfolder + "\\elev_" + "zone"+str(point[1]), currentresult) else: arcpy.Mosaic_management(currentsimfolder + "\\elev_" + "zone"+str(point[1]), currentresult, mosaic_type="MAXIMUM") #arcpy.Copy_management(str_output + "\\lisflood_res", str_output + "\\tmp_mosaic") #arcpy.Delete_management(str_output + "\\lisflood_res") # arcpy.MosaicToNewRaster_management(';'.join([str_output + "\\tmp_mosaic", str_output + "\\elev_" + point[1]]), # str_output,"lisflood_res", # pixel_type="32_BIT_FLOAT", # number_of_bands=1) except BaseException as e: filelog.write("ERREUR in " + simname + ": sim aborded during zone "+ str(point[1]) + "\n") messages.addWarningMessage("Some simulations skipped. See log file.") 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_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_RunSim(str_zonefolder, str_simfolder, str_lisfloodfolder, r_q, str_lakes, field_z, voutput, simtime, channelmanning, r_zbed, messages): str_inbci = str_zonefolder + "\\inbci.shp" str_outbci = str_zonefolder + "\\outbci.shp" zbed = RasterIO(r_zbed) discharge = RasterIO(r_q) # count est utilisé pour compter le nombre de zones, pour la barre de progression lors des simulations count = 0 bcipointcursor = arcpy.da.SearchCursor(str_inbci, ["SHAPE@", "zoneid", "flowacc", "type", "fpid"]) dictsegmentsin = {} for point in bcipointcursor: if point[1] not in dictsegmentsin: dictsegmentsin[point[1]] = [] dictsegmentsin[point[1]].append(point) allzones = list(dictsegmentsin.keys()) allzones.sort() dictzones_fp = {} for zone in allzones: if dictsegmentsin[zone][0][4] not in dictzones_fp: dictzones_fp[dictsegmentsin[zone][0][4]] = [] dictzones_fp[dictsegmentsin[zone][0][4]].append(zone) sortedzones = [] listfp = list(dictzones_fp.keys()) listfp.sort() for fp in listfp: listzones_fp = dictzones_fp[fp] listzones_fp.sort(reverse=True) sortedzones.extend(listzones_fp) # Ajout des information du fichier outbci.shp listzonesout = {} bcipointcursor = arcpy.da.SearchCursor(str_outbci, ["zoneid", "side", "lim1", "lim2", "side2", "lim3", "lim4", "SHAPE@"]) for point in bcipointcursor: listzonesout[point[0]] = point zones = str_zonefolder + "\\envelopezones.shp" # récupération du bci lac zonesscursor = arcpy.da.SearchCursor(zones, ["GRID_CODE", "SHAPE@", "Lake_ID"]) lakeid_byzone = {} for zoneshp in zonesscursor: if zoneshp[2] != -999: lakeid_byzone[zoneshp[0]] = zoneshp[2] # Z BCI fieldidlakes = arcpy.Describe(str_lakes).OIDFieldName shplakes = arcpy.da.SearchCursor(str_lakes, [fieldidlakes, field_z]) fieldz_bylakeid = {} for shplake in shplakes: fieldz_bylakeid[shplake[0]] = shplake[1] # Lancement de LISFLOOD-FP arcpy.SetProgressor("step", "Simulation 2D", 0, count, 1) progres = 0 arcpy.SetProgressorPosition(progres) if os.path.exists(str_simfolder + "\\lisflood_res"): arcpy.Delete_management(str_simfolder + "\\lisflood_res") for zone in sortedzones: segment = dictsegmentsin[zone] for point in sorted(segment, key=lambda q: q[2]): zonename = "zone" + str(point[1]) if point[3]=="main": if not arcpy.Exists(str_simfolder + "\\elev_zone" + str(point[1])): outpointshape = listzonesout[point[1]][7].firstPoint if point[1] in lakeid_byzone: hfix = fieldz_bylakeid[lakeid_byzone[point[1]]] else: if not os.path.exists(str_simfolder + "\\lisflood_res"): messages.addErrorMessage("Condition limite aval non trouvée : zone " + str(point[1])) else: # issue with Mosaic_management, used later with lisflood_res: # crash sometimes if the file is read here # so we make a tmp copy if arcpy.Exists(str_simfolder + "\\tmp_zone" + str(point[1])): arcpy.Delete_management(str_simfolder + "\\tmp_zone" + str(point[1])) arcpy.Copy_management(str_simfolder + "\\lisflood_res", str_simfolder + "\\tmp_zone" + str(point[1])) res_downstream = RasterIO(arcpy.Raster(str_simfolder + "\\tmp_zone" + str(point[1]))) hfix = res_downstream.getValue(res_downstream.YtoRow(outpointshape.Y), res_downstream.XtoCol(outpointshape.X)) if hfix == res_downstream.nodata: messages.addErrorMessage("Condition limite aval non trouvée : zone " + str(point[1])) arcpy.Delete_management(str_simfolder + "\\tmp_zone" + str(point[1])) # par newfile = str_simfolder + "\\zone" + str(point[1]) + ".par" filepar = open(newfile, 'w') filepar.write("DEMfile\tzone" + str(point[1]) + ".txt\n") filepar.write("resroot\tzone" + str(point[1]) + "\n") filepar.write("dirroot\t" + "res\n") filepar.write("manningfile\tnzone" + str(point[1]) + ".txt\n") filepar.write("bcifile\tzone" + str(point[1]) + ".bci" + "\n") filepar.write("sim_time\t" + str(simtime) + "\n") filepar.write("saveint\t" + str(simtime) + "\n") filepar.write("bdyfile\tzone" + str(point[1]) + ".bdy" + "\n") filepar.write("SGCwidth\twzone" + str(point[1]) + ".txt\n") filepar.write("SGCbank\tzone" + str(point[1]) + ".txt\n") filepar.write("SGCbed\tdzone" + str(point[1]) + ".txt\n") filepar.write("SGCn\t" + str(channelmanning) + "\n") filepar.write("chanmask\tmzone" + str(point[1]) + ".txt\n") # Vitesses du courant if voutput: filepar.write("qoutput\n") filepar.write("cfl\t0.5\n") filepar.write("max_Froude\t1\n") # filepar.write("debug\n") filepar.close() # bdy newfilebdy = str_simfolder + "\\zone" + str(point[1]) + ".bdy" for point2 in sorted(segment, key=lambda q: q[2]): raster_q_value = discharge.getValue(discharge.YtoRow(point2[0].firstPoint.Y), discharge.XtoCol(point2[0].firstPoint.X)) if point2[3] == "main": # Création du fichier bdy pointdischarge = raster_q_value / ( (discharge.raster.meanCellHeight + discharge.raster.meanCellWidth) / 2) lastdischarge = raster_q_value latnum = 0 filebdy = open(newfilebdy, 'w') filebdy.write("zone"+str(point[1]) + ".bdy\n") filebdy.write("zone"+str(point[1]) + "\n") filebdy.write("3\tseconds\n") filebdy.write("0\t0\n") filebdy.write("{0:.3f}".format(pointdischarge) + "\t50000\n") filebdy.write("{0:.3f}".format(pointdischarge) + "\t" + str(simtime)) filebdy.close() else: latnum += 1 pointdischarge = (raster_q_value - lastdischarge) / ( (discharge.raster.meanCellHeight + discharge.raster.meanCellWidth) / 2) lastdischarge = raster_q_value filebdy = open(newfilebdy, 'a') filebdy.write("\nzone" + str(point[1]) + "_" + str(latnum) + "\n") filebdy.write("3\tseconds\n") filebdy.write("0\t0\n") filebdy.write("{0:.3f}".format(pointdischarge) + "\t50000\n") filebdy.write("{0:.3f}".format(pointdischarge) + "\t" + str(simtime)) filebdy.close() # condition aval: 30cm au dessus du lit pour commencer zdep = min(zbed.getValue(zbed.YtoRow(outpointshape.Y), zbed.XtoCol(outpointshape.X)) + 0.3, hfix) filebdy = open(newfilebdy, 'a') filebdy.write("\nhvar\n") filebdy.write("4\tseconds\n") filebdy.write("{0:.2f}".format(zdep) + "\t0\n") filebdy.write("{0:.2f}".format(zdep) + "\t50000\n") filebdy.write("{0:.2f}".format(hfix) + "\t55000\n") filebdy.write("{0:.2f}".format(hfix) + "\t" + str(simtime)) filebdy.close() # calcul pour le -steadytol # Divise le débit par 200 et ne conserve qu'un chiffre significatif steadytol = str(round(lastdischarge / 200., - int(math.floor(math.log10(abs(lastdischarge / 200.)))))) subprocess.check_call([str_lisfloodfolder + "\\lisflood_intelRelease_double.exe", "-steady", "-steadytol", steadytol, str_simfolder + "\\zone" + str(point[1]) + ".par"], shell=True, cwd=str_simfolder) progres += 1 arcpy.SetProgressorPosition(progres) # Conversion des fichiers output # on renomme les fichiers créés (nécessaire pour être acceptés par l'outil de convsersion ASCII vers raster) if os.path.exists(str_simfolder + "\\res\\" + zonename + "elev.txt"): os.remove(str_simfolder + "\\res\\" + zonename + "elev.txt") if os.path.exists(str_simfolder + "\\res\\" + zonename + "-9999.elev"): os.rename(str_simfolder + "\\res\\" + zonename + "-9999.elev", str_simfolder + "\\res\\" + zonename + "elev.txt") else: os.rename(str_simfolder + "\\res\\" + zonename + "-0001.elev", str_simfolder + "\\res\\" + zonename + "elev.txt") messages.addWarningMessage("Steady state not reached : " + zonename) # Conversion des fichiers de sortie en raster pour ArcGIS str_elev = str_simfolder + "\\elev_" + zonename arcpy.ASCIIToRaster_conversion(str_simfolder + "\\res\\" + zonename + "elev.txt", str_elev, "FLOAT") # Ajout de la projection arcpy.DefineProjection_management(str_simfolder + "\\elev_" + zonename, r_q.spatialReference) messages.addMessage(str(point[1]) + " done") if not arcpy.Exists(str_simfolder + "\\lisflood_res"): arcpy.Copy_management(str_simfolder + "\\elev_" + zonename, str_simfolder + "\\lisflood_res") else: arcpy.Mosaic_management(str_simfolder + "\\elev_" + zonename, str_simfolder + "\\lisflood_res", mosaic_type="MAXIMUM") #arcpy.Copy_management(str_output + "\\lisflood_res", str_output + "\\tmp_mosaic") #arcpy.Delete_management(str_output + "\\lisflood_res") # arcpy.MosaicToNewRaster_management(';'.join([str_output + "\\tmp_mosaic", str_output + "\\elev_" + point[1]]), # str_output,"lisflood_res", # pixel_type="32_BIT_FLOAT", # number_of_bands=1) 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_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_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_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_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_DefBCI(r_flowdir, r_flowacc, distoutput, percent, str_zonesfolder, r_dem, r_width, r_zbed, r_manning, r_mask, str_outputfolder, messages): save_inbci = str_zonesfolder + "\\inbci.shp" save_outbci = str_zonesfolder + "\\outbci.shp" # Chargement des fichiers flowdir = RasterIO(r_flowdir) flowacc = RasterIO(r_flowacc) dem = RasterIO(r_dem) try: flowdir.checkMatch(flowacc) flowdir.checkMatch(dem) except Exception as e: messages.addErrorMessage(e.message) # Création d'un nouveau fichier de zones en prenant les enveloppes zones = str_zonesfolder + "\\envelopezones.shp" arcpy.FeatureEnvelopeToPolygon_management( str_zonesfolder + "\\polyzones.shp", zones) # Clip du DEM zonesscursor = arcpy.da.SearchCursor(zones, ["GRID_CODE", "SHAPE@"]) for zoneshp in zonesscursor: Xmin = zoneshp[1].extent.XMin Ymin = zoneshp[1].extent.YMin Xmax = zoneshp[1].extent.XMax Ymax = zoneshp[1].extent.YMax envelope = str(Xmin) + " " + str(Ymin) + " " + str(Xmax) + " " + str( Ymax) arcpy.Clip_management(dem.raster, envelope, str_zonesfolder + "\\zone" + str(zoneshp[0])) # Listes des points source et des points de sortie listinputpoints = [] listoutputpoints = [] # Lectures des points source pour chaque zone sourcepointcursor = arcpy.da.SearchCursor( str_zonesfolder + "\\sourcepoints.shp", ["SHAPE@", "ZoneID", "fpid"]) for sourcepoint in sourcepointcursor: newpoint = pointflowpath() newpoint.type = "main" newpoint.frompointid = sourcepoint[2] # Coordonnées du point source newpoint.X = sourcepoint[0].firstPoint.X newpoint.Y = sourcepoint[0].firstPoint.Y # Raster de la zone newpoint.numzone = sourcepoint[1] # Valeur du flow accumulation col = flowacc.XtoCol(newpoint.X) row = flowacc.YtoRow(newpoint.Y) newpoint.flowacc = flowacc.getValue(row, col) listinputpoints.append(newpoint) ### Début de traitement pour la détection des points de sortie et des points sources latéraux ### listlateralinputpoints = [] # Pour chaque raster, on parcourt l'écoulement à partir du point source for mainpoint in listinputpoints: # Raster de la zone correspondante au point source localraster = RasterIO( arcpy.Raster(str_zonesfolder + r"\zone" + str(mainpoint.numzone))) # Conversion des coordonnées currentcol = flowdir.XtoCol(mainpoint.X) currentrow = flowdir.YtoRow(mainpoint.Y) localcol = localraster.XtoCol(mainpoint.X) localrow = localraster.YtoRow(mainpoint.Y) currentflowacc = flowacc.getValue(currentrow, currentcol) mainpoint.flowacc = currentflowacc lastflowacc = currentflowacc # Parcours de l'écoulement intheraster = True while (intheraster): prevcol = currentcol prevrow = currentrow currentflowacc = flowacc.getValue(currentrow, currentcol) if 100. * float(currentflowacc - lastflowacc) / float(lastflowacc) >= percent: newpoint = pointflowpath() newpoint.type = "lateral" newpoint.frompointid = mainpoint.frompointid # Coordonnées du point source newpoint.X = flowdir.ColtoX(currentcol) newpoint.Y = flowdir.RowtoY(currentrow) # Raster de la zone newpoint.numzone = mainpoint.numzone # Valeur du flow accumulation newpoint.flowacc = currentflowacc lastflowacc = currentflowacc listlateralinputpoints.append(newpoint) # On cherche le prochain point à partir du flow direction direction = flowdir.getValue(currentrow, currentcol) if (direction == 1): currentcol = currentcol + 1 localcol += 1 if (direction == 2): currentcol = currentcol + 1 currentrow = currentrow + 1 localcol += 1 localrow += 1 if (direction == 4): currentrow = currentrow + 1 localrow += 1 if (direction == 8): currentcol = currentcol - 1 currentrow = currentrow + 1 localcol -= 1 localrow += 1 if (direction == 16): currentcol = currentcol - 1 localcol -= 1 if (direction == 32): currentcol = currentcol - 1 currentrow = currentrow - 1 localcol -= 1 localrow -= 1 if (direction == 64): currentrow = currentrow - 1 localrow -= 1 if (direction == 128): currentcol = currentcol + 1 currentrow = currentrow - 1 localcol += 1 localrow -= 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 localcol < 0 or localcol >= localraster.raster.width or localrow < 0 or localrow >= localraster.raster.height: intheraster = False elif localraster.getValue(localrow, localcol) == localraster.nodata: intheraster = False # On enregistre un point de sortie au dernier point traité avant de sortir de la zone newpoint = pointflowpath() newpoint.numzone = mainpoint.numzone newpoint.X = flowdir.ColtoX(prevcol) newpoint.Y = flowdir.RowtoY(prevrow) # Il est nécessaire d'enregistrer le côté du raster par lequel on sort. # Ceci est fait en regardant la distance entre le dernier point traité et les coordonnées maximales de la zone # Le côté de sortie est le côté pour lequel cette distance est minimum distside = min(newpoint.X - localraster.raster.extent.XMin, localraster.raster.extent.XMax - newpoint.X, newpoint.Y - localraster.raster.extent.YMin, localraster.raster.extent.YMax - newpoint.Y) if distside == newpoint.X - localraster.raster.extent.XMin: newpoint.side = "W" if distside == localraster.raster.extent.XMax - newpoint.X: newpoint.side = "E" if distside == newpoint.Y - localraster.raster.extent.YMin: newpoint.side = "S" if distside == localraster.raster.extent.YMax - newpoint.Y: newpoint.side = "N" listoutputpoints.append(newpoint) listinputpoints.extend(listlateralinputpoints) ### Fin de traitement pour la détection des points de sortie et des points sources latéraux ### ### Début de traitement pour la configuration des fenêtres de sortie ### # Pour chaque point de sortie for point in listoutputpoints: raster = RasterIO( arcpy.Raster(str_zonesfolder + r"\zone" + str(point.numzone))) colinc = 0 rowinc = 0 distinc = 0 point.side2 = "0" point.lim3 = 0 point.lim4 = 0 # Selon le coté de sortie, on progressera horizontalement ou verticalement if point.side == "W" or point.side == "E": rowinc = 1 distinc = raster.raster.meanCellHeight else: colinc = 1 distinc = raster.raster.meanCellWidth currentcol = raster.XtoCol(point.X) currentrow = raster.YtoRow(point.Y) distance = 0 # On progresse sur dans une direction jusqu'à sortir du raster ou jusqu'à ce que la distance voullue soit attente while (not (currentcol < 0 or currentcol >= raster.raster.width or currentrow < 0 or currentrow >= raster.raster.height)) \ and raster.getValue(currentrow,currentcol) != raster.nodata and distance < distoutput/2: distance += distinc currentrow += rowinc currentcol += colinc # On prends les coordonnées avant de sortir du raster currentrow -= rowinc currentcol -= colinc if point.side == "W" or point.side == "E": point.lim1 = raster.RowtoY(currentrow) else: point.lim1 = raster.ColtoX(currentcol) # Si la procédure s'est arrêtée parce qu'on est sorti du raster, on tourne de 90 degrés et on continue if distance < distoutput / 2: distance -= distinc if point.side == "W": colinc = 1 rowinc = 0 distinc = raster.raster.meanCellWidth point.lim3 = raster.raster.extent.XMin + ( currentcol + 0.5) * raster.raster.meanCellWidth elif point.side == "E": colinc = -1 rowinc = 0 distinc = raster.raster.meanCellWidth point.lim3 = raster.raster.extent.XMin + ( currentcol + 0.5) * raster.raster.meanCellWidth elif point.side == "N": rowinc = 1 colinc = 0 distinc = raster.raster.meanCellHeight point.lim3 = max( raster.raster.extent.YMin, raster.raster.extent.YMax - (currentrow + 1) * raster.raster.meanCellHeight ) + 0.5 * raster.raster.meanCellHeight elif point.side == "S": rowinc = -1 colinc = 0 distinc = raster.raster.meanCellHeight point.lim3 = max( raster.raster.extent.YMin, raster.raster.extent.YMax - (currentrow + 1) * raster.raster.meanCellHeight ) + 0.5 * raster.raster.meanCellHeight # On progresse à nouveau jusqu'à sortir du raster ou jusqu'à ce que la distance voullue soit attente while (not (currentcol < 0 or currentcol >= raster.raster.width or currentrow < 0 or currentrow >= raster.raster.height)) \ and raster.getValue(currentrow, currentcol) != raster.nodata and distance < distoutput / 2: distance += distinc currentrow += rowinc currentcol += colinc currentrow -= rowinc currentcol -= colinc # On cherche sur quel coté on est après avoir tourné de 90 degrés if point.side == "W" or point.side == "E": point.side2 = "S" point.lim4 = raster.raster.extent.XMin + ( currentcol + 0.5) * raster.raster.meanCellWidth else: point.side2 = "E" point.lim4 = max( raster.raster.extent.YMin, raster.raster.extent.YMax - (currentrow + 1) * raster.raster.meanCellHeight ) + 0.5 * raster.raster.meanCellHeight # On recommence toute la procédure de l'autre côté du point de sortie colinc = 0 rowinc = 0 distinc = 0 if point.side == "W" or point.side == "E": rowinc = -1 distinc = raster.raster.meanCellHeight else: colinc = -1 distinc = raster.raster.meanCellWidth currentcol = raster.XtoCol(point.X) currentrow = raster.YtoRow(point.Y) distance = 0 while (not (currentcol < 0 or currentcol >= raster.raster.width or currentrow < 0 or currentrow >= raster.raster.height)) \ and raster.getValue(currentrow, currentcol) != raster.nodata and distance < distoutput / 2: distance += distinc currentrow += rowinc currentcol += colinc currentrow -= rowinc currentcol -= colinc if point.side == "W" or point.side == "E": point.lim2 = max( raster.raster.extent.YMin, raster.raster.extent.YMax - (currentrow + 1) * raster.raster.meanCellHeight ) + 0.5 * raster.raster.meanCellHeight else: point.lim2 = raster.raster.extent.XMin + ( currentcol + 0.5) * raster.raster.meanCellWidth # Si la procédure s'est arrêtée parce qu'on est sorti du raster, on tourne de 90 degrés et on continue if distance < distoutput / 2: distance -= distinc if point.side == "W": colinc = 1 rowinc = 0 distinc = raster.raster.meanCellWidth point.lim3 = raster.raster.extent.XMin + ( currentcol + 0.5) * raster.raster.meanCellWidth elif point.side == "E": colinc = -1 rowinc = 0 distinc = raster.raster.meanCellWidth point.lim3 = raster.raster.extent.XMin + ( currentcol + 0.5) * raster.raster.meanCellWidth elif point.side == "N": rowinc = 1 colinc = 0 distinc = raster.raster.meanCellHeight point.lim3 = max( raster.raster.extent.YMin, raster.raster.extent.YMax - (currentrow + 1) * raster.raster.meanCellHeight ) + 0.5 * raster.raster.meanCellHeight elif point.side == "S": rowinc = -1 colinc = 0 distinc = raster.raster.meanCellHeight point.lim3 = max( raster.raster.extent.YMin, raster.raster.extent.YMax - (currentrow + 1) * raster.raster.meanCellHeight ) + 0.5 * raster.raster.meanCellHeight while (not (currentcol < 0 or currentcol >= raster.raster.width or currentrow < 0 or currentrow >= raster.raster.height)) \ and raster.getValue(currentrow, currentcol) != raster.nodata and distance < distoutput / 2: distance += distinc currentrow += rowinc currentcol += colinc currentrow -= rowinc currentcol -= colinc if point.side == "W" or point.side == "E": point.side2 = "N" point.lim4 = raster.raster.extent.XMin + ( currentcol + 0.5) * raster.raster.meanCellWidth else: point.side2 = "W" point.lim4 = max( raster.raster.extent.YMin, raster.raster.extent.YMax - (currentrow + 1) * raster.raster.meanCellHeight ) + 0.5 * raster.raster.meanCellHeight ### Fin du traitement pour la configuration des fenêtres de sortie ### # Création des shapefiles inbci et outbci, avec les champs nécessaires arcpy.CreateFeatureclass_management( os.path.dirname(save_inbci), os.path.basename(save_inbci), "POINT", spatial_reference=flowdir.raster.spatialReference) arcpy.AddField_management(save_inbci, "zoneid", "LONG") arcpy.AddField_management(save_inbci, "flowacc", "LONG") arcpy.AddField_management(save_inbci, "type", "TEXT") arcpy.AddField_management(save_inbci, "fpid", "LONG") arcpy.CreateFeatureclass_management( os.path.dirname(save_outbci), os.path.basename(save_outbci), "POINT", spatial_reference=flowdir.raster.spatialReference) arcpy.AddField_management(save_outbci, "zoneid", "LONG") arcpy.AddField_management(save_outbci, "side", "TEXT", field_length=1) arcpy.AddField_management(save_outbci, "lim1", "LONG") arcpy.AddField_management(save_outbci, "lim2", "LONG") arcpy.AddField_management( save_outbci, "side2", "TEXT", field_length=1, ) arcpy.AddField_management(save_outbci, "lim3", "LONG") arcpy.AddField_management(save_outbci, "lim4", "LONG") # Enregistrement dans les shapefiles des informations contenues dans les listes pointcursor = arcpy.da.InsertCursor( save_inbci, ["zoneid", "flowacc", "type", "fpid", "SHAPE@XY"]) for point in listinputpoints: pointcursor.insertRow([ point.numzone, point.flowacc, point.type, point.frompointid, (point.X, point.Y) ]) pointcursor = arcpy.da.InsertCursor(save_outbci, [ "zoneid", "side", "lim1", "lim2", "side2", "lim3", "lim4", "SHAPE@XY" ]) for point in listoutputpoints: pointcursor.insertRow([ point.numzone, point.side, point.lim1, point.lim2, point.side2, point.lim3, point.lim4, (point.X, point.Y) ]) del pointcursor # Création des fichiers .bci à partir des information du fichier inbci.shp bcipointcursor = arcpy.da.SearchCursor( save_inbci, ["SHAPE@", "zoneid", "flowacc", "type"]) dictsegmentsin = {} for point in bcipointcursor: if point[1] not in dictsegmentsin: dictsegmentsin[point[1]] = [] dictsegmentsin[point[1]].append(point) for segment in dictsegmentsin.values(): for point in sorted(segment, key=lambda q: q[2]): if point[3] == "main": latnum = 0 pointshape = point[0].firstPoint # Création du fichier newfile = str_outputfolder + "\\zone" + str(point[1]) + ".bci" # Enregistrement des coordonnées pour le point source filebci = open(newfile, 'w') filebci.write("P\t" + str(int(pointshape.X)) + "\t" + str(int(pointshape.Y)) + "\tQVAR\tzone" + str(point[1]) + "\n") filebci.close() if point[3] == "lateral": pointshape = point[0].firstPoint latnum += 1 newfile = str_outputfolder + "\\zone" + str(point[1]) + ".bci" # Enregistrement des coordonnées et du débit pour le point source filebci = open(newfile, 'a') filebci.write("P\t" + str(int(pointshape.X)) + "\t" + str(int(pointshape.Y)) + "\tQVAR\tzone" + str(point[1]) + "_" + str(latnum) + "\n") filebci.close() # Ajout de la zone de sortie au .bci bcipointcursor = arcpy.da.SearchCursor( save_outbci, ["zoneid", "side", "lim1", "lim2", "side2", "lim3", "lim4", "SHAPE@"]) for point in bcipointcursor: newfile = str_outputfolder + "\\zone" + str(point[0]) + ".bci" filebci = open(newfile, 'a') filebci.write(point[1] + "\t" + str(point[2]) + "\t" + str(point[3]) + "\tHVAR\thvar") if str(point[4]) != "0": filebci.write("\n" + str(point[4]) + "\t" + str(point[5]) + "\t" + str(point[6]) + "\tHVAR\thvar") filebci.close() # Création des fichiers .par et conversion des rasters en fichiers ASCII (un par point source comme il n'y a qu'un seul point d'entrée par simulation) for segment in dictsegmentsin.values(): for point in sorted(segment, key=lambda q: q[2]): if point[3] == "main": arcpy.Clip_management( r_width, "#", str_zonesfolder + r"\wzone" + str(point[1]), str_zonesfolder + "\\zone" + str(point[1]), "#", "NONE", "MAINTAIN_EXTENT") arcpy.Clip_management( r_zbed, "#", str_zonesfolder + r"\dzone" + str(point[1]), str_zonesfolder + "\\zone" + str(point[1]), "#", "NONE", "MAINTAIN_EXTENT") arcpy.Clip_management( r_manning, "#", str_zonesfolder + r"\nzone" + str(point[1]), str_zonesfolder + "\\zone" + str(point[1]), "#", "NONE", "MAINTAIN_EXTENT") arcpy.RasterToASCII_conversion( str_zonesfolder + "\\zone" + str(point[1]), str_outputfolder + "\\zone" + str(point[1]) + ".txt") arcpy.RasterToASCII_conversion( str_zonesfolder + "\dzone" + str(point[1]), str_outputfolder + "\\dzone" + str(point[1]) + ".txt") arcpy.RasterToASCII_conversion( str_zonesfolder + "\wzone" + str(point[1]), str_outputfolder + "\\wzone" + str(point[1]) + ".txt") arcpy.RasterToASCII_conversion( str_zonesfolder + "\\nzone" + str(point[1]), str_outputfolder + "\\nzone" + str(point[1]) + ".txt") arcpy.Delete_management(str_zonesfolder + r"\wzone" + str(point[1])) arcpy.Delete_management(str_zonesfolder + r"\dzone" + str(point[1])) arcpy.Delete_management(str_zonesfolder + r"\nzone" + str(point[1])) arcpy.Clip_management( r_mask, "#", str_zonesfolder + r"\mzone" + str(point[1]), str_zonesfolder + "\\zone" + str(point[1]), "#", "NONE", "MAINTAIN_EXTENT") arcpy.RasterToASCII_conversion( str_zonesfolder + "\mzone" + str(point[1]), str_outputfolder + "\\mzone" + str(point[1]) + ".txt") arcpy.Delete_management(str_zonesfolder + r"\mzone" + str(point[1])) 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