Exemple #1
0
def execute_SpatializeQ(r_flowdir, str_frompoint, r_flowacc, r_qpts, str_res,
                        interpolation):

    flowdir = RasterIO(r_flowdir)
    flowacc = RasterIO(r_flowacc)
    qpts = RasterIO(r_qpts)

    Res = RasterIO(r_flowdir, str_res, float, -255)
    trees = build_trees(flowdir, str_frompoint, Q=qpts, flowacc=flowacc)

    for tree in trees:
        # transmitting from upstream point
        for segment, prev_cs, cs in tree.uptodown_browsepts():

            cs.A = float(cs.flowacc)

            if cs.Q != qpts.nodata:
                cs.up_ptsA = cs.A
                cs.up_ptsQ = cs.Q
            elif prev_cs != None:
                cs.up_ptsA = prev_cs.up_ptsA
                cs.up_ptsQ = prev_cs.up_ptsQ
            else:
                cs.up_ptsA = 0
                cs.up_ptsQ = 0

        # transmitting from downstream point
        for segment, prev_cs, cs in tree.browsepts():

            if cs.Q != qpts.nodata:
                cs.down_ptsA = cs.A
                cs.down_ptsQ = cs.Q

            else:
                if prev_cs != None:
                    cs.down_ptsA = prev_cs.down_ptsA
                    cs.down_ptsQ = prev_cs.down_ptsQ
                else:
                    cs.down_ptsA = 0
                    cs.down_ptsQ = 0

                if interpolation:
                    cs.alpha = (cs.up_ptsQ - cs.down_ptsQ) / (cs.up_ptsA -
                                                              cs.down_ptsA)
                    cs.beta = cs.down_ptsQ - cs.alpha * cs.down_ptsA
                    cs.Q = cs.alpha * cs.A + cs.beta
                else:
                    if cs.down_ptsA == 0:
                        # cas particulier : pas d'interpolation (débit de crue), et extrapolation down
                        cs.Q = cs.up_ptsQ / cs.up_ptsA * cs.A
                    else:
                        cs.Q = cs.down_ptsQ / cs.down_ptsA * cs.A

        for segment in tree.treesegments():
            for pt in segment.get_profile():
                Res.setValue(pt.row, pt.col, pt.Q)

    Res.save()

    return
def execute_Simple1Dhydraulic(r_flowdir, str_frompoint, r_width, r_zbed, manning, result, r_Q, downstream_s, messages):



    flowdir = RasterIO(r_flowdir)
    zbed = RasterIO(r_zbed)
    width = RasterIO(r_width)
    Q = RasterIO(r_Q)


    trees = build_trees(flowdir, str_frompoint, width=width, z=zbed, Q=Q)


    Result = RasterIO(r_flowdir, result, float, -255)


    for tree in trees:
        downstream_end = True
        # 1D hydraulic calculations
        for segment, prev_cs, cs in tree.browsepts():

            if (cs.width == width.nodata or cs.z==zbed.nodata or cs.Q == Q.nodata):
                cs.skipped = True
                if not downstream_end:
                    messages.addErrorMessage("Missing data at "+str(cs.X)+", "+str(cs.Y))
            else:
                cs.skipped = False
                downstream_end = False
                cs.n = manning

                if prev_cs == None or prev_cs.skipped:

                    # downstream cs calculation
                    cs.s = downstream_s
                    manning_solver(cs)
                    cs.v = cs.Q / (cs.width * cs.y)
                    cs.h = cs.z + cs.y + cs.v ** 2 / (2 * g)
                    cs.Fr = cs.v / (g * cs.y) ** 0.5
                    cs.solver = "manning"
                    cs.type = 0


                else:

                    cs_solver(cs, prev_cs)

                cs.ws = cs.z + cs.y


        for segment in tree.treesegments():
            for pt in segment.get_profile():
                if not pt.skipped:
                    Result.setValue(pt.row, pt.col, pt.ws)


    Result.save()


    return
def execute_LinearInterpolation(r_flowdir,
                                str_frompoint,
                                r_values,
                                str_results,
                                messages,
                                language="FR"):

    # Chargement des fichiers
    flowdir = RasterIO(r_flowdir)
    bkfatcs = RasterIO(r_values)
    try:
        flowdir.checkMatch(bkfatcs)
    except Exception as e:
        messages.addErrorMessage(e.message)

    Result = RasterIO(r_flowdir, str_results, float, -255)

    # Décompte du nombre de points de départ pour configurer de la barre de progression
    count = 0
    frompointcursor = arcpy.da.SearchCursor(str_frompoint, "OID@")
    for frompoint in frompointcursor:
        count += 1
    progtext = "Traitement"
    if language == "EN":
        progtext = "Processing"
    arcpy.SetProgressor("step", progtext, 0, count, 1)
    progres = 0

    # Traitement effectué pour chaque point de départ
    frompointcursor = arcpy.da.SearchCursor(str_frompoint, ["OID@", "SHAPE@"])
    for frompoint in frompointcursor:
        # Mise à jour de la barre de progression
        arcpy.SetProgressorPosition(progres)
        progres += 1

        # On prend l'objet géométrique (le point) associé à la ligne dans la table
        frompointshape = frompoint[1].firstPoint

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(frompointshape.X)
        currentrow = flowdir.YtoRow(frompointshape.Y)

        intheraster = True
        # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters
        if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
            intheraster = False
        elif (flowdir.getValue(currentrow, currentcol) != 1
              and flowdir.getValue(currentrow, currentcol) != 2
              and flowdir.getValue(currentrow, currentcol) != 4
              and flowdir.getValue(currentrow, currentcol) != 8
              and flowdir.getValue(currentrow, currentcol) != 16
              and flowdir.getValue(currentrow, currentcol) != 32
              and flowdir.getValue(currentrow, currentcol) != 64
              and flowdir.getValue(currentrow, currentcol) != 128):
            intheraster = False

        listpointsflowpath = []
        listdistance = []
        listelevation = []
        totaldistance = 0
        currentdistance = 0
        confluence = False

        # Traitement effectué sur chaque cellule le long de l'écoulement
        while (intheraster):

            currentpoint = pointflowpath()
            currentpoint.row = currentrow
            currentpoint.col = currentcol
            totaldistance = totaldistance + currentdistance

            currentpoint.flowlength = totaldistance
            currentpoint.oncs = False

            # On crée une liste des points d'élévation connue le long de l'écoulement, ainsi qu'une liste associée avec leur distance depuis le point de distance
            if bkfatcs.getValue(currentrow, currentcol) != bkfatcs.nodata:
                if confluence:
                    # point après atteinte d'une confluence. On arrête le traitement
                    intheraster = False
                listdistance.append(totaldistance)
                listelevation.append(bkfatcs.getValue(currentrow, currentcol))
                currentpoint.oncs = True

            currentpoint.previouscsid = len(listdistance) - 1
            if not confluence:
                listpointsflowpath.append(currentpoint)

            # On cherche le prochain point à partir du flow direction
            direction = flowdir.getValue(currentrow, currentcol)
            if (direction == 1):
                currentcol = currentcol + 1
                currentdistance = flowdir.raster.meanCellWidth
            if (direction == 2):
                currentcol = currentcol + 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)
            if (direction == 4):
                currentrow = currentrow + 1
                currentdistance = flowdir.raster.meanCellHeight
            if (direction == 8):
                currentcol = currentcol - 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)
            if (direction == 16):
                currentcol = currentcol - 1
                currentdistance = flowdir.raster.meanCellWidth
            if (direction == 32):
                currentcol = currentcol - 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)
            if (direction == 64):
                currentrow = currentrow - 1
                currentdistance = flowdir.raster.meanCellHeight
            if (direction == 128):
                currentcol = currentcol + 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)

            # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters
            if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
                intheraster = False
            elif (flowdir.getValue(currentrow, currentcol) != 1
                  and flowdir.getValue(currentrow, currentcol) != 2
                  and flowdir.getValue(currentrow, currentcol) != 4
                  and flowdir.getValue(currentrow, currentcol) != 8
                  and flowdir.getValue(currentrow, currentcol) != 16
                  and flowdir.getValue(currentrow, currentcol) != 32
                  and flowdir.getValue(currentrow, currentcol) != 64
                  and flowdir.getValue(currentrow, currentcol) != 128):
                intheraster = False

            if intheraster:
                if (Result.getValue(currentrow, currentcol) != -255):
                    # Atteinte d'un confluent
                    # On continue encore jusqu'au prochain point
                    confluence = True

        if len(listdistance) <= 1:
            # Avertissement si il n'y a qu'un seul (ou aucun) point de données
            if language == "FR":
                messages.addWarningMessage(
                    "Point source {0}: pas assez de sections transversales".
                    format(frompoint[0]))
            else:
                messages.addWarningMessage(
                    "From point {0}: not enough cross-sections".format(
                        frompoint[0]))

        else:

            currentpointnumber = 0
            # Traitement pour chaque point le long de l'écoulement
            for currentpoint in listpointsflowpath:

                try:
                    if currentpoint.previouscsid == -1:
                        # cas particulier des premiers points avant une cs
                        # on prends la valeur de la premier cs
                        finalvalue = listelevation[0]
                    else:
                        if currentpoint.oncs:
                            # cas particulier : points sur une section transversale
                            finalvalue = listelevation[
                                currentpoint.previouscsid]
                        else:
                            finalvalue = listelevation[currentpoint.previouscsid]* \
                                         (listdistance[currentpoint.previouscsid + 1] - currentpoint.flowlength)/\
                                         (listdistance[currentpoint.previouscsid+1]-listdistance[currentpoint.previouscsid])\
                                         + listelevation[currentpoint.previouscsid+1]* \
                                         (currentpoint.flowlength - listdistance[currentpoint.previouscsid])/\
                                         (listdistance[currentpoint.previouscsid+1]-listdistance[currentpoint.previouscsid])
                except IndexError:
                    # IndexError lorsque l'on est en aval de la dernière section transversales
                    finalvalue = listelevation[-1]

                Result.setValue(currentpoint.row, currentpoint.col, finalvalue)

                currentpointnumber = currentpointnumber + 1

    Result.save()

    return
def execute_FloodAndChannel(r_dem,
                            r_elevation,
                            r_flowdir,
                            r_slope,
                            str_frompoints,
                            threshold_slope,
                            threshold_growth,
                            maxiter,
                            str_output,
                            messages,
                            language="FR"):

    # Chargement des fichiers
    dem = RasterIO(r_dem)
    elevation = RasterIO(r_elevation)
    slope = None
    if r_slope is not None:
        slope = RasterIO(r_slope)
    flowdir = RasterIO(r_flowdir)
    try:
        dem.checkMatch(flowdir)
        dem.checkMatch(elevation)
        if slope is not None:
            dem.checkMatch(slope)
    except Exception as e:
        messages.addErrorMessage(e.message)

    # Fichier temporaire créé dans le "Scratch folder"
    randomname = binascii.hexlify(os.urandom(6)).decode()
    temp_flood = arcpy.env.scratchWorkspace + "\\" + str(randomname)
    Result = RasterIO(r_dem, temp_flood, float, -255)

    # Décompte du nombre de points de départ pour configurer de la barre de progression
    frompointcursor = arcpy.da.SearchCursor(str_frompoints, "SHAPE@")
    count = 0
    for frompoint in frompointcursor:
        count += 1
    progtext = "Traitement"
    if language == "EN":
        progtext = "Processing"
    arcpy.SetProgressor("step", progtext, 0, count, 1)
    progres = 0

    # Traitement effectué pour chaque point de départ
    frompointcursor = arcpy.da.SearchCursor(str_frompoints, ["SHAPE@", "OID@"])
    for frompoint in frompointcursor:
        # Mise à jour de la barre de progression
        arcpy.SetProgressorPosition(progres)
        progres += 1

        # On prend l'objet géométrique (le point) associé à la ligne dans la table
        frompointshape = frompoint[0].firstPoint

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(frompointshape.X)
        currentrow = flowdir.YtoRow(frompointshape.Y)

        intheraster = True
        # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters
        if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
            intheraster = False
        elif (flowdir.getValue(currentrow, currentcol) != 1
              and flowdir.getValue(currentrow, currentcol) != 2
              and flowdir.getValue(currentrow, currentcol) != 4
              and flowdir.getValue(currentrow, currentcol) != 8
              and flowdir.getValue(currentrow, currentcol) != 16
              and flowdir.getValue(currentrow, currentcol) != 32
              and flowdir.getValue(currentrow, currentcol) != 64
              and flowdir.getValue(currentrow, currentcol) != 128):
            intheraster = False

        listnewcells = []

        # Première itération: on ajoute les cellules pour la rivière, le long de l'écoulement
        while (intheraster):

            point = pointflowpath()
            point.row = currentrow
            point.col = currentcol
            point.elev = elevation.getValue(currentrow, currentcol)
            listnewcells.append(point)
            Result.setValue(currentrow, currentcol, point.elev)

            # On cherche le prochain point à partir du flow direction
            direction = flowdir.getValue(currentrow, currentcol)
            if (direction == 1):
                currentcol = currentcol + 1

            if (direction == 2):
                currentcol = currentcol + 1
                currentrow = currentrow + 1

            if (direction == 4):
                currentrow = currentrow + 1

            if (direction == 8):
                currentcol = currentcol - 1
                currentrow = currentrow + 1

            if (direction == 16):
                currentcol = currentcol - 1

            if (direction == 32):
                currentcol = currentcol - 1
                currentrow = currentrow - 1

            if (direction == 64):
                currentrow = currentrow - 1

            if (direction == 128):
                currentcol = currentcol + 1
                currentrow = currentrow - 1

            # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters
            if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
                intheraster = False
            elif (flowdir.getValue(currentrow, currentcol) != 1
                  and flowdir.getValue(currentrow, currentcol) != 2
                  and flowdir.getValue(currentrow, currentcol) != 4
                  and flowdir.getValue(currentrow, currentcol) != 8
                  and flowdir.getValue(currentrow, currentcol) != 16
                  and flowdir.getValue(currentrow, currentcol) != 32
                  and flowdir.getValue(currentrow, currentcol) != 64
                  and flowdir.getValue(currentrow, currentcol) != 128):
                intheraster = False

            if intheraster:
                if (Result.getValue(currentrow, currentcol) != Result.nodata):
                    # Atteinte d'un confluent
                    intheraster = False

        lengthflowpath = len(listnewcells)

        # Itération réalisée jusqu'à atteinte du seuil de croissance négligeable, avec aggrandissement de la largeur d'une cellule à chaque itération
        iteration = 0
        while ((float(len(listnewcells)) / float(lengthflowpath)) >=
               threshold_growth) and iteration < maxiter:

            currentlistnewcells = []

            iteration += 1
            # Pour chaque cellule que l'on a ajoutée à l'itération précédente...
            while (len(listnewcells) > 0):
                currentpoint = listnewcells.pop()
                # ... on test les cellules voisines
                for i in range(1, 5):
                    neighbourcol = currentpoint.col
                    neighbourrow = currentpoint.row
                    if i == 1:
                        neighbourcol += 1
                    elif i == 2:
                        neighbourcol -= 1
                    elif i == 3:
                        neighbourrow += 1
                    elif i == 4:
                        neighbourrow -= 1

                    try:
                        # Si la cellule voisine existe et n'a pas déjà été testée...
                        if (Result.getValue(neighbourrow, neighbourcol)
                                == Result.nodata) and dem.getValue(
                                    neighbourrow, neighbourcol) != dem.nodata:
                            testslope = True
                            if slope is not None:
                                testslope = slope.getValue(
                                    neighbourrow,
                                    neighbourcol) < threshold_slope
                            # ... on teste si la cellule testée est dans le chenal / inondée ...
                            if (dem.getValue(neighbourrow, neighbourcol) <
                                    currentpoint.elev) and testslope:
                                #... auquel cas on mets à jour le fichier de résultat et la liste des cellules ajoutées par l'itération en cours
                                Result.setValue(neighbourrow, neighbourcol,
                                                currentpoint.elev)
                                point = pointflowpath()
                                point.row = neighbourrow
                                point.col = neighbourcol
                                point.elev = currentpoint.elev
                                currentlistnewcells.append(point)

                            else:
                                # Les cellules testées négativement sont mises à -999 pour éviter de les tester à nouveau
                                Result.setValue(neighbourrow, neighbourcol,
                                                -999)
                    except IndexError:
                        # Exception déclenchée et à ignorer lorsque l'on est sur le bord du raster
                        pass
            listnewcells.extend(currentlistnewcells)

    # On supprime les -999 du résultat final
    Result.save()
    raster_res = arcpy.sa.SetNull(temp_flood, temp_flood, "VALUE = -999")
    raster_res.save(str_output)
    arcpy.Delete_management(temp_flood)

    return
Exemple #5
0
def execute_BedAssessment(r_flowdird4, str_frompoint, r_width, r_zwater, manning, result, r_Q, downstream_s, messages):



    flowdir = RasterIO(r_flowdird4)
    zwater = RasterIO(r_zwater)
    width = RasterIO(r_width)
    Q = RasterIO(r_Q)


    trees = build_trees(flowdir, str_frompoint, width=width, wslidar=zwater, Q=Q)


    Result = RasterIO(r_flowdird4, result, float, -255)


    for tree in trees:
        enditeration = False
        iteration = 0
        downstream_end = True
        while not enditeration:
            iteration += 1
            print (iteration)

            # 1D hydraulic calculations
            prevsegid = 0
            for segment, prev_cs, cs in tree.browsepts():

                if (cs.width == width.nodata or cs.wslidar==zwater.nodata or cs.Q == Q.nodata):
                    cs.skipped = True
                    if not downstream_end and iteration == 1:
                        messages.addWarningMessage("Missing data at "+str(cs.X)+", "+str(cs.Y))
                else:
                    cs.skipped = False
                    downstream_end = False
                    cs.n = manning

                    if iteration == 1:
                        cs.z = cs.wslidar
                        cs.ws = cs.wslidar

                    if prev_cs == None or prev_cs.skipped:

                        # downstream cs calculation
                        cs.s = downstream_s
                        manning_solver(cs)
                        cs.v = cs.Q / (cs.width * cs.y)
                        cs.h = cs.z + cs.y + cs.v ** 2 / (2 * g)
                        cs.Fr = cs.v / (g * cs.y) ** 0.5
                        cs.solver = "manning"
                        cs.type = 0


                    else:

                        cs_solver(cs, prev_cs)


                    cs.prev_ws = cs.ws
                    cs.ws = cs.z + cs.y
                    cs.dif = cs.ws - cs.wslidar


                    prevsegid = segment.id


            corrections = []
            # down to up
            for segment, prev_cs, cs in tree.browsepts():
                if not cs.skipped:
                    if prev_cs != None and not prev_cs.skipped:
                        if prev_cs.z_fill > cs.z:
                            if prev_cs.z == prev_cs.z_fill:
                                # first backwater cell
                                correction = []
                                corrections.append(correction)
                                cs.idcorrection = len(corrections) - 1
                            else:
                                correction = corrections[prev_cs.idcorrection]
                                cs.idcorrection = prev_cs.idcorrection
                            cs.z_fill = prev_cs.z_fill
                            correction.append(cs)
                        else:
                            cs.z_fill = cs.z
                            correction = []
                            correction.append(cs)
                            corrections.append(correction)
                            cs.idcorrection = len(corrections) - 1
                    else:
                        cs.z_fill = cs.z
                        correction = []
                        correction.append(cs)
                        corrections.append(correction)
                        cs.idcorrection = len(corrections) - 1

            enditeration = True
            for correction in corrections:
                sumdif = 0
                sumdifws = 0
                for cscorrect in correction:
                    sumdif += cscorrect.dif
                    sumdifws += cscorrect.ws - cscorrect.prev_ws
                correcteddif = sumdif / len(correction)
                difws = abs(sumdifws) / len(correction)
                if difws > 0.01:
                    for cscorrect in correction:
                        cscorrect.z = cscorrect.z - correcteddif
                    enditeration = False



        for segment in tree.treesegments():
            for pt in segment.get_profile():
                if not pt.skipped:
                    Result.setValue(pt.row, pt.col, pt.z)


    Result.save()


    return
Exemple #6
0
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
Exemple #7
0
def execute_WSprofile(r_flowdir, str_frompoint, r_z, str_zws, messages):

    flowdir = RasterIO(r_flowdir)
    z = RasterIO(r_z)

    trees = build_trees(flowdir, str_frompoint, z=z)

    zws = RasterIO(r_flowdir, str_zws, float, -255)

    for tree in trees:
        goodslope = False
        iteration = 0
        while not goodslope:

            iteration += 1
            corrections = []
            # down to up
            for segment, prev_cs, cs in tree.browsepts():
                if prev_cs is not None:
                    cs.z_fill = max(prev_cs.z_fill, cs.z)
                else:
                    cs.z_fill = cs.z
                if iteration == 1:
                    cs.originalfill = cs.z_fill
                # z_breach à None permet le bon breach pour les parties parcourues plusieurs fois
                cs.z_breach = None
            # up to down
            for segment, prev_cs, cs in tree.uptodown_browsepts():
                if prev_cs is not None:
                    if cs.z_breach is not None:
                        cs.z_breach = min(prev_cs.z_breach, cs.z, cs.z_breach)
                    else:
                        cs.z_breach = min(prev_cs.z_breach, cs.z)
                else:
                    cs.z_breach = cs.z
                if iteration == 1:
                    cs.originalbreach = cs.z_breach

            # down to up
            for segment, prev_cs, cs in tree.browsepts():
                if prev_cs is not None:
                    if cs.z_breach == prev_cs.z_breach and cs.z_fill == prev_cs.z_fill:
                        # ajout de la cs à la correction
                        correction = corrections[prev_cs.idcorrection]
                        correction.append(cs)
                        cs.idcorrection = prev_cs.idcorrection
                    else:
                        # nouvelle correction
                        correction = []
                        correction.append(cs)
                        corrections.append(correction)
                        cs.idcorrection = len(corrections) - 1
                else:
                    correction = []
                    correction.append(cs)
                    corrections.append(correction)
                    cs.idcorrection = len(corrections) - 1

            for correction in corrections:
                sumz2 = 0
                for cscorrect in correction:
                    sumz2 += cscorrect.z**2
                correctedz = (sumz2 / len(correction))**0.5
                for cscorrect in correction:
                    cscorrect.z = correctedz

            # test goodslope
            goodslope = True
            # up to down
            for segment, prev_cs, cs in tree.uptodown_browsepts():
                if prev_cs != None and cs.z > prev_cs.z:
                    goodslope = False

        for segment in tree.treesegments():
            for pt in segment.get_profile():
                zws.setValue(pt.row, pt.col, pt.z)

    zws.save()

    return
Exemple #8
0
def execute_BankfullAtCS(r_dem, r_flowdir, str_frompoints, r_cs, p_detect, thresholdz, increment, str_bkf, messages, language = "FR"):



    # Chargement des fichiers
    dem = RasterIO(r_dem)
    flowdir = RasterIO(r_flowdir)
    cs = RasterIO(r_cs)
    try:
        dem.checkMatch(flowdir)
        dem.checkMatch(cs)
    except Exception as e:
        messages.addErrorMessage(str(e))

    Result = RasterIO(r_dem, str_bkf, float,-255)

    # Décompte du nombre de points de départ pour configurer de la barre de progression
    frompointcursor = arcpy.da.SearchCursor(str_frompoints, "OID@")
    count = 0
    for frompoint in frompointcursor:
        count += 1
    progtext= "Calcul des élévations plein-bord aux sections transversales"
    if language == "EN":
        progtext = "Computing elevation at cross-sections"
    arcpy.SetProgressor("step", progtext, 0, count, 1)
    progres = 0

    # Traitement effectué pour chaque point de départ
    frompointcursor = arcpy.da.SearchCursor(str_frompoints, "SHAPE@")
    for frompoint in frompointcursor:
        # Mise à jour de la barre de progression
        arcpy.SetProgressorPosition(progres)
        progres += 1

        # On prend l'objet géométrique (le point) associé à la ligne dans la table
        frompointshape = frompoint[0].firstPoint

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(frompointshape.X)
        currentrow = flowdir.YtoRow(frompointshape.Y)

        intheraster = True
        # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters
        if currentcol<0 or currentcol>=flowdir.raster.width or currentrow<0 or currentrow>= flowdir.raster.height:
            intheraster = False
        elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and
                      flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and
                      flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and
                      flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128):
            intheraster = False

        # Traitement effectué sur chaque cellule le long de l'écoulement
        while (intheraster):

            # Traitement effectué sur chaque section transversale
            if cs.getValue(currentrow,currentcol) != cs.nodata:


                zmin = dem.getValue(currentrow,currentcol)
                angle = cs.getValue(currentrow,currentcol)


                MaxHydroH = 0
                HydroH = 0

                stophydroh = False
                previouslisth = []
                previouslisth.append(zmin)
                previousstep = 0
                prevz = zmin
                previouslisth2 = []
                previouslisth2.append(zmin)
                previousstep2 = 0
                prevz2 = zmin
                n = 4
                # itérations, par incrément de 10 cm
                while n < (thresholdz/increment) and not stophydroh :
                    n += 1
                    # currentz : élévation plein-bord testée
                    currentz = zmin + increment*n

                    listh = list(previouslisth)
                    step = previousstep
                    stop = False
                    # Déplacement le long de la section transversale
                    while not stop:
                        step += 1
                        # calcul de la ligne et de la colonne du prochain point dans l'axe de la section transversale
                        if (angle > math.pi / 4 and angle < 3 * math.pi / 4):
                            rowinc = -step
                            colinc = int(math.cos(angle)*step)
                        else:
                            colinc = step
                            rowinc = -int(math.sin(angle)*step)
                        if angle > 3 * math.pi / 4:
                            rowinc = -rowinc
                        # localz : élévation du sol pour le point testé le long de la section transversale
                        localz = dem.getValue(currentrow + rowinc, currentcol + colinc)
                        # on arrête d'avancer le long de la section transversale quand l'élévation devient plus grande que l'élévation plein-bord testée (ou si on sort du raster)
                        if localz != dem.nodata:
                            if localz < prevz:
                                localz = prevz
                            if localz >= currentz:
                                stop = True
                            prevz = localz
                        else:
                            stop = True
                        listh.append(localz)
                    if(len(listh)>2):
                        previousstep = step -1
                        previouslisth = listh[:len(listh)-1]
                    sumh = 0

                    # Pour toutes les élévations sauf la première
                    for i in range(1,len(listh)):
                        if i<len(listh)-1:
                            # Toutes les élévations sauf la dernière.
                            # Aire = panneau trapezoidale
                            sumh+= (currentz-listh[i-1]+currentz-listh[i])/2
                        elif listh[i]!=dem.nodata:
                            # Dernière élévation : plus haute que currentz.
                            # Aire = formule pour le petit triangle
                            sumh += (currentz-listh[i-1])*(currentz-listh[i-1])/(listh[i]-listh[i-1])/2
                            step -= 1
                            step += (currentz - listh[i - 1]) / (listh[i] - listh[i - 1])
                        else:
                            # Dernière élévation : No Data
                            # Pas d'aire calculée pour ce panneau
                            step-=1
                    # on répète les opérations précédentes en progressant dans l'autre sens le long de la section transversale

                    listh = list(previouslisth2)
                    step2 = previousstep2

                    stop = False

                    while not stop:
                        step2 += 1
                        if (angle > math.pi / 4 and angle < 3 * math.pi / 4):
                            rowinc = -step2
                            colinc = int(math.cos(angle) * step2)
                        else:
                            colinc = step2
                            rowinc = -int(math.sin(angle) * step2)
                        if angle > 3 * math.pi / 4:
                            rowinc = -rowinc
                        localz = dem.getValue(currentrow - rowinc, currentcol - colinc)



                        if localz != dem.nodata:
                            if localz < prevz2:
                                localz = prevz2
                            if localz >= currentz:
                                stop = True
                            prevz2 = localz
                        else:
                            stop = True

                        listh.append(localz)
                    if(len(listh)>2):
                        previousstep2 = step2 -1
                        previouslisth2 = listh[:len(listh)-1]
                    sumh2 = 0
                    for i in range(1, len(listh)):
                        if i < len(listh) - 1:
                            sumh2 += (currentz - listh[i - 1] + currentz - listh[i]) / 2
                        elif listh[i] != dem.nodata:
                            sumh2 += (currentz - listh[i - 1]) * (currentz - listh[i - 1]) / (
                            listh[i] - listh[i - 1]) / 2
                            step2 -= 1
                            step2 += (currentz - listh[i - 1]) / (listh[i] - listh[i - 1])
                        else:
                            step2-=1



                    # Calcul de la profondeur moyenne
                    # Note: erreur de +1 au lieu de -1 ds la version EPRI1
                    HydroH = (sumh + sumh2) / (step + step2)

                    # Le critère pour détecter le niveau plein-bord est-il respecté ?
                    if (HydroH < (1-p_detect/100)*MaxHydroH):
                        # si oui, on prends la dernière élévation plein-bord testé, moins 10 cm
                        bkfh = currentz - increment
                        stophydroh = True
                    MaxHydroH = max(HydroH, MaxHydroH)

                # stophydroh est vrai si un niveau plein-bord a été détecté
                if stophydroh:
                    Result.setValue(currentrow,currentcol,bkfh)





            # On cherche le prochain point à partir du flow direction
            direction = flowdir.getValue(currentrow, currentcol)
            if (direction == 1):
                currentcol = currentcol + 1

            if (direction == 2):
                currentcol = currentcol + 1
                currentrow = currentrow + 1

            if (direction == 4):
                currentrow = currentrow + 1

            if (direction == 8):
                currentcol = currentcol - 1
                currentrow = currentrow + 1

            if (direction == 16):
                currentcol = currentcol - 1

            if (direction == 32):
                currentcol = currentcol - 1
                currentrow = currentrow - 1

            if (direction == 64):
                currentrow = currentrow - 1

            if (direction == 128):
                currentcol = currentcol + 1
                currentrow = currentrow - 1

            # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters
            if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
                intheraster = False
            elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and
                          flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and
                          flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and
                          flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128):
                intheraster = False

            if intheraster:
                if (Result.getValue(currentrow, currentcol) != -255):
                    # Atteinte d'un confluent
                    intheraster = False



    Result.save()


    return
def execute_Slope(r_dem,
                  r_flowdir,
                  str_frompoint,
                  distancesmoothingpath,
                  save_slope,
                  save_newfp,
                  messages,
                  language="FR"):

    # Chargement des fichiers
    DEM = RasterIO(r_dem)
    FlowDir = RasterIO(r_flowdir)
    try:
        DEM.checkMatch(FlowDir)
    except Exception as e:
        messages.addErrorMessage(e.message)

    Result = RasterIO(r_flowdir, save_slope, float, -255)

    # Liste des nouveaux points de départ
    listfirstpoints = []
    # Décompte du nombre de points de départ pour configurer de la barre de progression
    frompointcursor = arcpy.da.SearchCursor(str_frompoint, "OID@")
    count = 0
    for frompoint in frompointcursor:
        count += 1
    progtext = "Calcul des pentes"
    if language == "EN":
        progtext = "Processing"
    arcpy.SetProgressor("step", progtext, 0, count, 1)
    progres = 0
    # Traitement effectué pour chaque point de départ
    frompointcursor = arcpy.da.SearchCursor(str_frompoint, "SHAPE@")
    for frompoint in frompointcursor:

        # Mise à jour de la barre de progression
        arcpy.SetProgressorPosition(progres)
        progres += 1

        # On prend l'objet géométrique (le point) associé à la ligne dans la table
        frompointshape = frompoint[0].firstPoint

        # Conversion des coordonnées
        currentcol = FlowDir.XtoCol(frompointshape.X)
        currentrow = FlowDir.YtoRow(frompointshape.Y)

        intheraster = True
        # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters
        if currentcol < 0 or currentcol >= FlowDir.raster.width or currentrow < 0 or currentrow >= FlowDir.raster.height:
            intheraster = False
        elif (FlowDir.getValue(currentrow, currentcol) != 1
              and FlowDir.getValue(currentrow, currentcol) != 2
              and FlowDir.getValue(currentrow, currentcol) != 4
              and FlowDir.getValue(currentrow, currentcol) != 8
              and FlowDir.getValue(currentrow, currentcol) != 16
              and FlowDir.getValue(currentrow, currentcol) != 32
              and FlowDir.getValue(currentrow, currentcol) != 64
              and FlowDir.getValue(currentrow, currentcol) != 128):
            intheraster = False

        listpointsflowpath = []
        totaldistance = 0
        currentdistance = 0
        confluencedist = 0

        firstpoint = True

        # Traitement effectué sur chaque cellule le long de l'écoulement
        while (intheraster):

            # On met à jour la liste des points le long de l'écoulement
            currentpoint = pointflowpath()
            currentpoint.row = currentrow
            currentpoint.col = currentcol
            currentpoint.addeddistance = currentdistance
            totaldistance = totaldistance + currentdistance
            currentpoint.distance = totaldistance
            listpointsflowpath.append(currentpoint)

            # les points sont mis à -999 (cela permet la détection des confluences)
            if confluencedist == 0:
                Result.setValue(currentrow, currentcol, -999)

            # On cherche le prochain point à partir du flow direction
            direction = FlowDir.getValue(currentrow, currentcol)
            if (direction == 1):
                currentcol = currentcol + 1
                currentdistance = FlowDir.raster.meanCellWidth
            if (direction == 2):
                currentcol = currentcol + 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(FlowDir.raster.meanCellWidth *
                                            FlowDir.raster.meanCellWidth +
                                            FlowDir.raster.meanCellHeight *
                                            FlowDir.raster.meanCellHeight)
            if (direction == 4):
                currentrow = currentrow + 1
                currentdistance = FlowDir.raster.meanCellHeight
            if (direction == 8):
                currentcol = currentcol - 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(FlowDir.raster.meanCellWidth *
                                            FlowDir.raster.meanCellWidth +
                                            FlowDir.raster.meanCellHeight *
                                            FlowDir.raster.meanCellHeight)
            if (direction == 16):
                currentcol = currentcol - 1
                currentdistance = FlowDir.raster.meanCellWidth
            if (direction == 32):
                currentcol = currentcol - 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(FlowDir.raster.meanCellWidth *
                                            FlowDir.raster.meanCellWidth +
                                            FlowDir.raster.meanCellHeight *
                                            FlowDir.raster.meanCellHeight)
            if (direction == 64):
                currentrow = currentrow - 1
                currentdistance = FlowDir.raster.meanCellHeight
            if (direction == 128):
                currentcol = currentcol + 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(FlowDir.raster.meanCellWidth *
                                            FlowDir.raster.meanCellWidth +
                                            FlowDir.raster.meanCellHeight *
                                            FlowDir.raster.meanCellHeight)

            # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters
            if currentcol < 0 or currentcol >= FlowDir.raster.width or currentrow < 0 or currentrow >= FlowDir.raster.height:
                intheraster = False
            elif (FlowDir.getValue(currentrow, currentcol) != 1
                  and FlowDir.getValue(currentrow, currentcol) != 2
                  and FlowDir.getValue(currentrow, currentcol) != 4
                  and FlowDir.getValue(currentrow, currentcol) != 8
                  and FlowDir.getValue(currentrow, currentcol) != 16
                  and FlowDir.getValue(currentrow, currentcol) != 32
                  and FlowDir.getValue(currentrow, currentcol) != 64
                  and FlowDir.getValue(currentrow, currentcol) != 128):
                intheraster = False

            if intheraster:
                if (Result.getValue(currentrow, currentcol) != -255):
                    # Atteinte d'un confluent
                    if confluencedist == 0:
                        confluencedist = totaldistance + currentdistance

                    # On continue encore sur la distance de calcul de la pente après le confluent
                    if (totaldistance + currentdistance -
                            confluencedist) > distancesmoothingpath:
                        intheraster = False

        currentpointnumber = 0
        # Pour chaque point le long de l'écoulement
        while (currentpointnumber < len(listpointsflowpath)):

            currentpoint = listpointsflowpath[currentpointnumber]

            listpointforregression = []
            listpointforregression.append(currentpoint)
            distancefromcurrentpoint = 0
            nbcellsfromcurrentpoint = 0
            try:
                # on s'éloigne du point courant, en allant vers l'amont, jusqu'à dépasser la distance de calcul de la pente
                while (distancefromcurrentpoint <= distancesmoothingpath / 2):
                    nbcellsfromcurrentpoint = nbcellsfromcurrentpoint - 1
                    if (currentpointnumber + nbcellsfromcurrentpoint >= 0):
                        # on mets à jour la distance jusqu'au point courant
                        distancefromcurrentpoint = distancefromcurrentpoint + listpointsflowpath[
                            currentpointnumber +
                            nbcellsfromcurrentpoint].addeddistance
                        # on ajoute le point aux points à utiliser pour la régression (calcul de la pente au point courant)
                        listpointforregression.append(
                            listpointsflowpath[currentpointnumber +
                                               nbcellsfromcurrentpoint])
                    else:
                        # la distance à l'extrémité amont est plus petie que la distance de calcul de pente
                        raise IndexError
                distancefromcurrentpoint = 0
                nbcellsfromcurrentpoint = 0
                # même chose en s'éliognant du point courant vers l'aval
                while (distancefromcurrentpoint < distancesmoothingpath / 2):
                    nbcellsfromcurrentpoint = nbcellsfromcurrentpoint + 1
                    if (currentpointnumber + nbcellsfromcurrentpoint <
                            len(listpointsflowpath)):
                        distancefromcurrentpoint = distancefromcurrentpoint + listpointsflowpath[
                            currentpointnumber +
                            nbcellsfromcurrentpoint].addeddistance
                        listpointforregression.append(
                            listpointsflowpath[currentpointnumber +
                                               nbcellsfromcurrentpoint])
                    else:
                        # la distance à l'extrémité aval est plus petite que la distance de calcul de pente
                        raise IndexError

                # Calcul de la régression linéaire
                sumdistance = 0
                sumelevation = 0
                sumdistanceelevation = 0
                sumsquaredistance = 0
                for pointforregression in listpointforregression:
                    sumdistance = sumdistance + pointforregression.distance
                    sumelevation = sumelevation + DEM.getValue(
                        pointforregression.row, pointforregression.col)
                    sumdistanceelevation = sumdistanceelevation + pointforregression.distance * \
                                                                  DEM.getValue(pointforregression.row,
                                                                               pointforregression.col)
                    sumsquaredistance = sumsquaredistance + pointforregression.distance * pointforregression.distance

                slope = -(len(listpointforregression) * sumdistanceelevation -
                          sumdistance * sumelevation) / (
                              len(listpointforregression) * sumsquaredistance -
                              sumdistance * sumdistance)

                Result.setValue(currentpoint.row, currentpoint.col, slope)

                if firstpoint:
                    # S'il s'agit du premier point (pour ce point de départ) pour lequel une valeur de pente est calculée, on enregistre ce point dans la liste des points de départ des pentes
                    newpoint = arcpy.Point(
                        FlowDir.raster.extent.XMin + (currentpoint.col + 0.5) *
                        FlowDir.raster.meanCellWidth,
                        FlowDir.raster.extent.YMax - (currentpoint.row + 0.5) *
                        FlowDir.raster.meanCellHeight)
                    listfirstpoints.append(newpoint)
                    firstpoint = False

            except IndexError:
                # pas de calcul de la pente pour les extrémité amont et aval (il n'y a pas la distance suffisante pour le calcul de la pente)
                pass

            currentpointnumber = currentpointnumber + 1

    Result.save()
    # On supprime les -999 du résultat final
    raster_res = arcpy.sa.SetNull(save_slope, save_slope, "VALUE = -999")
    raster_res.save(save_slope)

    # on enregistre la liste des points de départ des pente
    arcpy.CreateFeatureclass_management(os.path.dirname(save_newfp),
                                        os.path.basename(save_newfp),
                                        "POINT",
                                        spatial_reference=r_flowdir)
    pointcursor = arcpy.da.InsertCursor(save_newfp, "SHAPE@XY")
    for point in listfirstpoints:
        pointcursor.insertRow([(point.X, point.Y)])

    return
def execute_D8toD4(r_flowdir,
                   r_dem,
                   str_frompoint,
                   str_result,
                   messages,
                   language="FR"):
    """The source code of the tool."""

    # Chargement des fichiers
    flowdir = RasterIO(r_flowdir)
    dem = RasterIO(r_dem)
    try:
        dem.checkMatch(flowdir)
    except Exception as e:
        messages.addErrorMessage(e.message)

    Result = RasterIO(r_flowdir, str_result, float, -255)

    donepoints = __Frompoint_paths()

    # Traitement effectué pour chaque point de départ
    frompointcursor = arcpy.da.SearchCursor(str_frompoint, ["SHAPE@", "OID@"])
    for frompoint in frompointcursor:

        # On prend l'objet géométrique (le point) associé à la ligne dans la table
        frompointshape = frompoint[0].firstPoint

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(frompointshape.X)
        currentrow = flowdir.YtoRow(frompointshape.Y)

        intheraster = True
        # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters
        if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
            intheraster = False
        elif (flowdir.getValue(currentrow, currentcol) != 1
              and flowdir.getValue(currentrow, currentcol) != 2
              and flowdir.getValue(currentrow, currentcol) != 4
              and flowdir.getValue(currentrow, currentcol) != 8
              and flowdir.getValue(currentrow, currentcol) != 16
              and flowdir.getValue(currentrow, currentcol) != 32
              and flowdir.getValue(currentrow, currentcol) != 64
              and flowdir.getValue(currentrow, currentcol) != 128):
            intheraster = False

        # Traitement effectué sur chaque cellule le long de l'écoulement

        while (intheraster):

            # On regarde la valeur du "flow direction"
            direction = flowdir.getValue(currentrow, currentcol)
            donepoints.add_point(currentrow, currentcol, frompoint[1])
            # Si cette valeur est 1, 4, 16 ou 64, on se déplace sur des cases adjacentes. On garde la valeur.
            # Si cette valeur est 2, 8, 32 ou 128, on se déplace en diagonale. Un traitement est nécesaire.

            if (direction == 1):
                Result.setValue(currentrow, currentcol, direction)
                currentcol = currentcol + 1

            if (direction == 2):

                # on regarde, parmi les deux cellules adjacentes pouvant remplacer le déplacement en diagonale, quelle est celle d'élévation la plus basse, et on passe par celle-ci
                # exemple : direction = 2 -> on se déplace en diagonale, en bas à droite
                # on peut donc remplacer ce déplacement par aller à droite (flow direction = 1) puis aller en bas (flow direction = 4) ou bien aller en bas puis aller à droite
                if dem.getValue(currentrow, currentcol + 1) is None:
                    Result.setValue(currentrow, currentcol, 1)
                    intheraster = False
                elif dem.getValue(currentrow + 1, currentcol) is None:
                    Result.setValue(currentrow, currentcol, 4)
                    intheraster = False
                elif dem.getValue(currentrow, currentcol + 1) < dem.getValue(
                        currentrow + 1, currentcol):
                    # La cellule à droite à une élévation plus basse que la cellule en bas, on choisie donc d'aller à droite puis ensuite en bas
                    # On modifie donc le flow direction pour aller à droite
                    Result.setValue(currentrow, currentcol, 1)
                    # Puis on modifie le flow direction du la cellule à droite pour aller en bas
                    if donepoints.done_previously(currentrow, currentcol + 1,
                                                  frompoint[1]):
                        # Atteinte d'un confluent
                        intheraster = False
                    else:
                        Result.setValue(currentrow, currentcol + 1, 4)
                        donepoints.add_point(currentrow, currentcol + 1,
                                             frompoint[1])
                else:
                    Result.setValue(currentrow, currentcol, 4)
                    if donepoints.done_previously(currentrow + 1, currentcol,
                                                  frompoint[1]):
                        # Atteinte d'un confluent
                        intheraster = False
                    else:
                        Result.setValue(currentrow + 1, currentcol, 1)
                        donepoints.add_point(currentrow + 1, currentcol,
                                             frompoint[1])
                currentcol = currentcol + 1
                currentrow = currentrow + 1

            if (direction == 4):
                Result.setValue(currentrow, currentcol, direction)
                currentrow = currentrow + 1

            if (direction == 8):
                if dem.getValue(currentrow + 1, currentcol) is None:
                    Result.setValue(currentrow, currentcol, 4)
                    intheraster = False
                elif dem.getValue(currentrow, currentcol - 1) is None:
                    Result.setValue(currentrow, currentcol, 16)
                    intheraster = False
                elif dem.getValue(currentrow + 1, currentcol) < dem.getValue(
                        currentrow, currentcol - 1):
                    Result.setValue(currentrow, currentcol, 4)
                    if donepoints.done_previously(currentrow + 1, currentcol,
                                                  frompoint[1]):
                        # Atteinte d'un confluent
                        intheraster = False
                    else:
                        Result.setValue(currentrow + 1, currentcol, 16)
                        donepoints.add_point(currentrow + 1, currentcol,
                                             frompoint[1])
                else:
                    Result.setValue(currentrow, currentcol, 16)
                    if donepoints.done_previously(currentrow, currentcol - 1,
                                                  frompoint[1]):
                        # Atteinte d'un confluent
                        intheraster = False
                    else:
                        Result.setValue(currentrow, currentcol - 1, 4)
                        donepoints.add_point(currentrow, currentcol - 1,
                                             frompoint[1])
                currentcol = currentcol - 1
                currentrow = currentrow + 1

            if (direction == 16):
                Result.setValue(currentrow, currentcol, direction)
                currentcol = currentcol - 1

            if (direction == 32):
                if dem.getValue(currentrow - 1, currentcol) is None:
                    Result.setValue(currentrow, currentcol, 64)
                    intheraster = False
                elif dem.getValue(currentrow, currentcol - 1) is None:
                    Result.setValue(currentrow, currentcol, 16)
                    intheraster = False
                elif dem.getValue(currentrow - 1, currentcol) < dem.getValue(
                        currentrow, currentcol - 1):
                    Result.setValue(currentrow, currentcol, 64)
                    if donepoints.done_previously(currentrow - 1, currentcol,
                                                  frompoint[1]):
                        # Atteinte d'un confluent
                        intheraster = False
                    else:
                        Result.setValue(currentrow - 1, currentcol, 16)
                        donepoints.add_point(currentrow - 1, currentcol,
                                             frompoint[1])
                else:
                    Result.setValue(currentrow, currentcol, 16)
                    if donepoints.done_previously(currentrow, currentcol - 1,
                                                  frompoint[1]):
                        # Atteinte d'un confluent
                        intheraster = False
                    else:
                        Result.setValue(currentrow, currentcol - 1, 64)
                        donepoints.add_point(currentrow, currentcol - 1,
                                             frompoint[1])
                currentcol = currentcol - 1
                currentrow = currentrow - 1

            if (direction == 64):
                Result.setValue(currentrow, currentcol, direction)
                currentrow = currentrow - 1

            if (direction == 128):
                if dem.getValue(currentrow - 1, currentcol) is None:
                    Result.setValue(currentrow, currentcol, 64)
                    intheraster = False
                elif dem.getValue(currentrow, currentcol + 1) is None:
                    Result.setValue(currentrow, currentcol, 1)
                    intheraster = False
                elif dem.getValue(currentrow - 1, currentcol) < dem.getValue(
                        currentrow, currentcol + 1):
                    Result.setValue(currentrow, currentcol, 64)
                    if donepoints.done_previously(currentrow - 1, currentcol,
                                                  frompoint[1]):
                        # Atteinte d'un confluent
                        intheraster = False
                    else:
                        Result.setValue(currentrow - 1, currentcol, 1)
                        donepoints.add_point(currentrow - 1, currentcol,
                                             frompoint[1])
                else:
                    Result.setValue(currentrow, currentcol, 1)
                    if donepoints.done_previously(currentrow, currentcol + 1,
                                                  frompoint[1]):
                        # Atteinte d'un confluent
                        intheraster = False
                    else:
                        Result.setValue(currentrow, currentcol + 1, 64)
                        donepoints.add_point(currentrow, currentcol + 1,
                                             frompoint[1])
                currentcol = currentcol + 1
                currentrow = currentrow - 1

            if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
                intheraster = False
            elif (flowdir.getValue(currentrow, currentcol) != 1
                  and flowdir.getValue(currentrow, currentcol) != 2
                  and flowdir.getValue(currentrow, currentcol) != 4
                  and flowdir.getValue(currentrow, currentcol) != 8
                  and flowdir.getValue(currentrow, currentcol) != 16
                  and flowdir.getValue(currentrow, currentcol) != 32
                  and flowdir.getValue(currentrow, currentcol) != 64
                  and flowdir.getValue(currentrow, currentcol) != 128):
                intheraster = False

            if intheraster:
                if donepoints.done_previously(currentrow, currentcol,
                                              frompoint[1]):
                    # Atteinte d'un confluent
                    intheraster = False

    Result.save()

    return
def execute_FlowLength(r_flowdir,
                       str_frompoint,
                       str_result,
                       riverline,
                       messages,
                       language="FR"):
    """The source code of the tool."""

    flowdir = RasterIO(r_flowdir)

    Result = RasterIO(r_flowdir, str_result, float, -255)

    frompointcursor = arcpy.da.SearchCursor(str_frompoint, "SHAPE@")
    for frompoint in frompointcursor:
        frompointshape = frompoint[0].firstPoint

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(frompointshape.X)
        currentrow = flowdir.YtoRow(frompointshape.Y)

        intheraster = True
        if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
            intheraster = False
        elif (flowdir.getValue(currentrow, currentcol) != 1
              and flowdir.getValue(currentrow, currentcol) != 2
              and flowdir.getValue(currentrow, currentcol) != 4
              and flowdir.getValue(currentrow, currentcol) != 8
              and flowdir.getValue(currentrow, currentcol) != 16
              and flowdir.getValue(currentrow, currentcol) != 32
              and flowdir.getValue(currentrow, currentcol) != 64
              and flowdir.getValue(currentrow, currentcol) != 128):
            intheraster = False

        totaldistance = 0
        currentdistance = 0

        while (intheraster):

            totaldistance = totaldistance + currentdistance

            Result.setValue(currentrow, currentcol, totaldistance)

            # looking for the next point
            direction = flowdir.getValue(currentrow, currentcol)
            if (direction == 1):
                currentcol = currentcol + 1
                currentdistance = flowdir.raster.meanCellWidth
            if (direction == 2):
                currentcol = currentcol + 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)
            if (direction == 4):
                currentrow = currentrow + 1
                currentdistance = flowdir.raster.meanCellHeight
            if (direction == 8):
                currentcol = currentcol - 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)
            if (direction == 16):
                currentcol = currentcol - 1
                currentdistance = flowdir.raster.meanCellWidth
            if (direction == 32):
                currentcol = currentcol - 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)
            if (direction == 64):
                currentrow = currentrow - 1
                currentdistance = flowdir.raster.meanCellHeight
            if (direction == 128):
                currentcol = currentcol + 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)

            if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
                intheraster = False
            elif (flowdir.getValue(currentrow, currentcol) != 1
                  and flowdir.getValue(currentrow, currentcol) != 2
                  and flowdir.getValue(currentrow, currentcol) != 4
                  and flowdir.getValue(currentrow, currentcol) != 8
                  and flowdir.getValue(currentrow, currentcol) != 16
                  and flowdir.getValue(currentrow, currentcol) != 32
                  and flowdir.getValue(currentrow, currentcol) != 64
                  and flowdir.getValue(currentrow, currentcol) != 128):
                intheraster = False

            if intheraster:
                if (Result.getValue(currentrow, currentcol) != Result.nodata):
                    # Atteinte d'une confluence
                    intheraster = False

    Result.save()

    if riverline is not None:
        r_rivers = arcpy.sa.SetNull(arcpy.sa.IsNull(Result.raster), 1,
                                    "VALUE = 1")
        arcpy.RasterToPolyline_conversion(r_rivers, riverline)

    return
def execute_CS(r_flowdir, str_frompoints, distance, str_cs, messages, language = "FR"):

    # Chargement des fichiers
    flowdir = RasterIO(r_flowdir)

    # Fichier temporaire créé dans le "Scratch folder"
    temp_cs = arcpy.CreateScratchName("temp_cs", data_type="RasterDataset", workspace=arcpy.env.scratchFolder)
    Result = RasterIO(r_flowdir, temp_cs, float, -255)

    # Décompte du nombre de points de départ pour configurer de la barre de progression
    frompointcursor = arcpy.da.SearchCursor(str_frompoints, "OID@")
    count = 0
    for frompoint in frompointcursor:
        count += 1
    progtext = "Calcul de l'emplacement des sections transversales"
    if language == "EN":
        progtext = "Placing cross-sections"
    arcpy.SetProgressor("step", progtext, 0, count, 1)
    progres = 0

    # Traitement effectué pour chaque point de départ
    frompointcursor = arcpy.da.SearchCursor(str_frompoints, "SHAPE@")
    for frompoint in frompointcursor:
        # Mise à jour de la barre de progression
        arcpy.SetProgressorPosition(progres)
        progres += 1

        # On prend l'objet géométrique (le point) associé à la ligne dans la table
        frompointshape = frompoint[0].firstPoint

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(frompointshape.X)
        currentrow = flowdir.YtoRow(frompointshape.Y)

        # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters
        intheraster = True
        if currentcol<0 or currentcol>=flowdir.raster.width or currentrow<0 or currentrow>= flowdir.raster.height:
            intheraster = False
        elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and
                      flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and
                      flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and
                      flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128):
            intheraster = False



        totaldistance = 0
        currentdistance = 0
        lastpointdistance = 0

        # Traitement effectué sur chaque cellule le long de l'écoulement
        while (intheraster):

            totaldistance = totaldistance + currentdistance

            # Entre deux sections transversales, les points sont mis à -999 (cela permet la détection des confluences)
            if totaldistance <= lastpointdistance + distance:
                Result.setValue(currentrow, currentcol, -999)
            else:
                Result.setValue(currentrow, currentcol, 1)
                lastpointdistance = totaldistance

            # On cherche le prochain point à partir du flow direction
            direction = flowdir.getValue(currentrow, currentcol)
            if (direction == 1):
                currentcol = currentcol + 1
                currentdistance = flowdir.raster.meanCellWidth
            if (direction == 2):
                currentcol = currentcol + 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(
                    flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight)
            if (direction == 4):
                currentrow = currentrow + 1
                currentdistance = flowdir.raster.meanCellHeight
            if (direction == 8):
                currentcol = currentcol - 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(
                    flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight)
            if (direction == 16):
                currentcol = currentcol - 1
                currentdistance = flowdir.raster.meanCellWidth
            if (direction == 32):
                currentcol = currentcol - 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(
                    flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight)
            if (direction == 64):
                currentrow = currentrow - 1
                currentdistance = flowdir.raster.meanCellHeight
            if (direction == 128):
                currentcol = currentcol + 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(
                    flowdir.raster.meanCellWidth * flowdir.raster.meanCellWidth + flowdir.raster.meanCellHeight * flowdir.raster.meanCellHeight)

            # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters
            if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
                intheraster = False
            elif (flowdir.getValue(currentrow, currentcol) != 1 and flowdir.getValue(currentrow, currentcol) != 2 and
                          flowdir.getValue(currentrow, currentcol) != 4 and flowdir.getValue(currentrow, currentcol) != 8 and
                          flowdir.getValue(currentrow, currentcol) != 16 and flowdir.getValue(currentrow, currentcol) != 32 and
                          flowdir.getValue(currentrow, currentcol) != 64 and flowdir.getValue(currentrow, currentcol) != 128):
                intheraster = False

            if intheraster:
                if (Result.getValue(currentrow, currentcol) != -255):
                    # Atteinte d'un confluent
                    intheraster = False




    # On supprime les -999 du résultat final
    Result.save()
    raster_res = arcpy.sa.SetNull(temp_cs, temp_cs, "VALUE = -999")
    # randomname = binascii.hexlify(os.urandom(6))
    # temp_cs2 = arcpy.env.scratchWorkspace + "\\" + randomname
    # raster_res.save(temp_cs2)

    arcpy.RasterToPoint_conversion(raster_res, str_cs)


    arcpy.Delete_management(temp_cs)
    #arcpy.Delete_management(temp_cs2)
    return
Exemple #13
0
def execute_WSsmoothing(r_flowdir,
                        str_frompoint,
                        r_z,
                        r_zerr,
                        str_zwssm,
                        smooth_perc=0.9):

    flowdir = RasterIO(r_flowdir)
    z = RasterIO(r_z)

    zerr = RasterIO(r_zerr)
    zwssm = RasterIO(r_flowdir, str_zwssm, float, -255)

    trees = build_trees(flowdir, str_frompoint, zerr=zerr, ztosmooth=z)

    for tree in trees:
        for segment, prev_cs, cs in tree.browsepts():
            if prev_cs != None:
                cs.z_fill = max(prev_cs.z_fill, cs.zerr)
            else:
                cs.z_fill = cs.zerr
            # z_breach à None permet le bon breach pour les parties parcourues plusieurs fois
            cs.z_breach = None
        # up to down
        for segment, prev_cs, cs in tree.uptodown_browsepts():
            if prev_cs != None:
                if cs.z_breach != None:
                    cs.z_breach = min(prev_cs.z_breach, cs.zerr, cs.z_breach)
                else:
                    cs.z_breach = min(prev_cs.z_breach, cs.zerr)
            else:
                cs.z_breach = cs.zerr

        # indépendance par rapport à la résolution:
        #   La méthode de base pondère le résultat final en fonction de la valeur au point et de la valeur précédente
        #   (majorée/minorée par le fill ou le breach). L'indépendance par rapport à la résolution est faire en corrigeant
        #   le poid par la puissance du ratio des distances. Le poid de base était pensé pour une résolution de 10m.
        #   Ex : Résolution de 2m. On parcourt 5 pixels pour l'équivalent de un pixel à 10m. Si le poid est de 0.9
        #   pour 10m), z = 0.9z, dans le cas d'une chute à 0 (profil en forme de marche), il faut à 2m de résolution
        #   z*poid^5 pour avoir l'équivalent, donc poid^5=0.9, donc poid=0.9^(1/5)
        # down to up
        for segment, prev_cs, cs in tree.browsepts():
            if prev_cs != None:

                #cs.zsmooth2 = (1-smooth_perc**(cs.dist/10.))*cs.ztosmooth + smooth_perc**(cs.dist/10.)*max(prev_cs.zsmooth2, cs.z_breach)
                cs.zsmooth2 = max(
                    ((1 - smooth_perc**(cs.dist / 10.)) * cs.ztosmooth +
                     smooth_perc**(cs.dist / 10.) * prev_cs.zsmooth2),
                    cs.z_breach)

            else:
                cs.zsmooth2 = cs.ztosmooth
        # up to down
        for segment, prev_cs, cs in tree.uptodown_browsepts():
            if prev_cs != None:
                if hasattr(cs, "zsmooth1"):
                    #cs.zsmooth1 = min((1 - smooth_perc**(cs.dist/10.)) * cs.ztosmooth + smooth_perc**(cs.dist/10.) * min(prev_cs.zsmooth1, cs.z_fill), cs.zsmooth1)
                    cs.zsmooth1 = min(
                        ((1 - smooth_perc**(cs.dist / 10.)) * cs.ztosmooth +
                         smooth_perc**(cs.dist / 10.) * prev_cs.zsmooth1),
                        cs.z_fill, cs.zsmooth1)
                else:
                    #cs.zsmooth1 = (1-smooth_perc**(cs.dist/10.))*cs.ztosmooth + smooth_perc**(cs.dist/10.)*min(prev_cs.zsmooth1, cs.z_fill)
                    cs.zsmooth1 = min(
                        ((1 - smooth_perc**(cs.dist / 10.)) * cs.ztosmooth +
                         smooth_perc**(cs.dist / 10.) * prev_cs.zsmooth1),
                        cs.z_fill)
            else:
                cs.zsmooth1 = cs.ztosmooth
            cs.zsmooth = (cs.zsmooth1 + cs.zsmooth2) / 2

        for segment in tree.treesegments():
            for pt in segment.get_profile():

                zwssm.setValue(pt.row, pt.col, pt.zsmooth)

    zwssm.save()
    return
Exemple #14
0
def execute_RiverWith(r_binary,
                      r_flowdir,
                      str_frompoints,
                      r_cs,
                      oriented,
                      str_width,
                      messages,
                      language="FR"):

    # Chargement des fichiers
    binary = RasterIO(r_binary)
    flowdir = RasterIO(r_flowdir)
    cs = RasterIO(r_cs)
    try:
        flowdir.checkMatch(cs)
    except Exception as e:
        messages.addErrorMessage(e.message)

    Result = RasterIO(r_flowdir, str_width, float, -255)

    # Décompte du nombre de points de départ pour configurer de la barre de progression
    frompointcursor = arcpy.da.SearchCursor(str_frompoints, "OID@")
    count = 0
    for frompoint in frompointcursor:
        count += 1

    progtext = "Calcul de la largeur aux sections transversales"
    if language == "EN":
        progtext = "Processing"
    arcpy.SetProgressor("step", progtext, 0, count, 1)
    progres = 0

    # Traitement effectué pour chaque point de départ
    frompointcursor = arcpy.da.SearchCursor(str_frompoints, "SHAPE@")
    for frompoint in frompointcursor:
        # Mise à jour de la barre de progression
        arcpy.SetProgressorPosition(progres)
        progres += 1

        # On prend l'objet géométrique (le point) associé à la ligne dans la table
        frompointshape = frompoint[0].firstPoint

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(frompointshape.X)
        currentrow = flowdir.YtoRow(frompointshape.Y)

        intheraster = True
        # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters
        if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
            intheraster = False
        elif (flowdir.getValue(currentrow, currentcol) != 1
              and flowdir.getValue(currentrow, currentcol) != 2
              and flowdir.getValue(currentrow, currentcol) != 4
              and flowdir.getValue(currentrow, currentcol) != 8
              and flowdir.getValue(currentrow, currentcol) != 16
              and flowdir.getValue(currentrow, currentcol) != 32
              and flowdir.getValue(currentrow, currentcol) != 64
              and flowdir.getValue(currentrow, currentcol) != 128):
            intheraster = False

        # Traitement effectué sur chaque cellule le long de l'écoulement
        while (intheraster):

            # On se reprojète dans le système de coordonnées du raster binary
            colbinary = binary.XtoCol(flowdir.ColtoX(currentcol))
            rowbinary = binary.YtoRow(flowdir.RowtoY(currentrow))

            angle = cs.getValue(currentrow, currentcol)
            if angle != cs.nodata:

                if oriented:
                    # calcul de la ligne et de la colonne du prochain point dans l'axe de la section transversale
                    if (angle > math.pi / 4 and angle < 3 * math.pi / 4):
                        rowinc = -1
                        colinc = math.cos(angle)
                    else:
                        colinc = 1
                        rowinc = -math.sin(angle)
                    if angle > 3 * math.pi / 4:
                        rowinc = -rowinc

                    step = 0

                    while binary.getValue(
                            rowbinary + int(rowinc * step),
                            colbinary + int(colinc * step)) != binary.nodata:
                        step += 1

                    # on répète les opérations précédentes en progressant dans l'autre sens le long de la section transversale
                    step2 = 0

                    while binary.getValue(
                            rowbinary - int(rowinc * step2),
                            colbinary - int(colinc * step2)) != binary.nodata:
                        step2 += 1

                    # if the process was not interrupted because an edge was reached
                    if (rowbinary + int(rowinc * step)) >= 0 and (
                            colbinary + int(colinc * step)
                    ) >= 0 and (rowbinary - int(rowinc * step2)) >= 0 and (
                            colbinary - int(colinc * step2)
                    ) and (rowbinary + int(rowinc * step)
                           ) < binary.raster.height and (colbinary + int(
                               colinc * step)) < binary.raster.width and (
                                   rowbinary - int(rowinc * step2)
                               ) < binary.raster.height and (colbinary - int(
                                   colinc * step2)) < binary.raster.width:

                        basedist = math.sqrt(
                            (rowinc * binary.raster.meanCellHeight)**2 +
                            (colinc * binary.raster.meanCellWidth)**2)

                        width = basedist * (step + step2)
                        Result.setValue(currentrow, currentcol, width)

                else:
                    # on teste la largeur sur une étoile à 16 branches et on prend le minimum
                    minwidth = None
                    for star_i in range(1, 9):
                        step = 0
                        step2 = 0
                        if star_i == 1:
                            rowinc = 0
                            colinc = 1
                        if star_i == 2:
                            rowinc = step % 2
                            colinc = 1
                        if star_i == 3:
                            rowinc = 1
                            colinc = 1
                        if star_i == 4:
                            rowinc = 1
                            colinc = step % 2
                        if star_i == 5:
                            rowinc = 1
                            colinc = 0
                        if star_i == 6:
                            rowinc = 1
                            colinc = -step % 2
                        if star_i == 7:
                            rowinc = 1
                            colinc = -1
                        if star_i == 8:
                            rowinc = step % 2
                            colinc = -1

                        while binary.getValue(
                                rowbinary + int(rowinc * step), colbinary +
                                int(colinc * step)) != binary.nodata:
                            step += 1

                        while binary.getValue(
                                rowbinary - int(rowinc * step2), colbinary -
                                int(colinc * step2)) != binary.nodata:
                            step2 += 1

                        width = None
                        # if the process was not interrupted because an edge was reached
                        if (rowbinary + int(rowinc * step)) >= 0 and (
                                colbinary + int(colinc * step)
                        ) >= 0 and (rowbinary - int(rowinc * step2)) >= 0 and (
                                colbinary - int(colinc * step2)
                        ) and (rowbinary +
                               int(rowinc * step)) < binary.raster.height and (
                                   colbinary + int(colinc * step)
                               ) < binary.raster.width and (
                                   rowbinary - int(rowinc * step2)
                               ) < binary.raster.height and (colbinary - int(
                                   colinc * step2)) < binary.raster.width:
                            basedist = math.sqrt(
                                (rowinc * binary.raster.meanCellHeight)**2 +
                                (colinc * binary.raster.meanCellWidth)**2)

                            width = basedist * (step + step2)

                        if minwidth is not None:
                            if width is not None:
                                minwidth = min(minwidth, width)
                        else:
                            minwidth = width

                    if minwidth is not None:
                        Result.setValue(currentrow, currentcol, minwidth)

            # On cherche le prochain point à partir du flow direction
            direction = flowdir.getValue(currentrow, currentcol)
            if (direction == 1):
                currentcol = currentcol + 1

            if (direction == 2):
                currentcol = currentcol + 1
                currentrow = currentrow + 1

            if (direction == 4):
                currentrow = currentrow + 1

            if (direction == 8):
                currentcol = currentcol - 1
                currentrow = currentrow + 1

            if (direction == 16):
                currentcol = currentcol - 1

            if (direction == 32):
                currentcol = currentcol - 1
                currentrow = currentrow - 1

            if (direction == 64):
                currentrow = currentrow - 1

            if (direction == 128):
                currentcol = currentcol + 1
                currentrow = currentrow - 1

            # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters
            if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
                intheraster = False
            elif (flowdir.getValue(currentrow, currentcol) != 1
                  and flowdir.getValue(currentrow, currentcol) != 2
                  and flowdir.getValue(currentrow, currentcol) != 4
                  and flowdir.getValue(currentrow, currentcol) != 8
                  and flowdir.getValue(currentrow, currentcol) != 16
                  and flowdir.getValue(currentrow, currentcol) != 32
                  and flowdir.getValue(currentrow, currentcol) != 64
                  and flowdir.getValue(currentrow, currentcol) != 128):
                intheraster = False

            if intheraster:
                if (Result.getValue(currentrow, currentcol) != -255):
                    # Atteinte d'un confluent
                    intheraster = False

    Result.save()

    return
def execute_Breach(r_dem,
                   r_flowdir,
                   str_frompoint,
                   SaveResult,
                   messages,
                   language="FR"):

    # Chargement des fichiers
    dem = RasterIO(r_dem)
    flowdir = RasterIO(r_flowdir)
    try:
        dem.checkMatch(flowdir)
    except Exception as e:
        messages.addErrorMessage(str(e))
    Result = RasterIO(r_flowdir, SaveResult, float, -255)

    # Traitement effectué pour chaque point de départ
    frompointcursor = arcpy.da.SearchCursor(str_frompoint, "SHAPE@")
    for frompoint in frompointcursor:

        # On prend l'objet géométrique (le point) associé à la ligne dans la table
        frompointshape = frompoint[0].firstPoint

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(frompointshape.X)
        currentrow = flowdir.YtoRow(frompointshape.Y)

        # prev_z : élévation au point précédent (= élévation du point testé pour le premier point)
        prev_z = dem.getValue(currentrow, currentcol)

        # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters
        intheraster = True
        if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
            intheraster = False
        elif (flowdir.getValue(currentrow, currentcol) != 1
              and flowdir.getValue(currentrow, currentcol) != 2
              and flowdir.getValue(currentrow, currentcol) != 4
              and flowdir.getValue(currentrow, currentcol) != 8
              and flowdir.getValue(currentrow, currentcol) != 16
              and flowdir.getValue(currentrow, currentcol) != 32
              and flowdir.getValue(currentrow, currentcol) != 64
              and flowdir.getValue(currentrow, currentcol) != 128):
            intheraster = False
        if dem.getValue(currentrow, currentcol) == dem.nodata:
            intheraster = False

        confluence = False

        # Traitement effectué sur chaque cellule le long de l'écoulement
        while (intheraster):

            if not confluence:
                # L'élévation finale du point testé (z) est la valeur la plus petite entre son élévation actuelle et l'élévation du point précédent (prev_z)
                newz = dem.getValue(currentrow, currentcol)
            else:
                # Si on a atteint une confluence, on continue jusqu'à ce que qu'on atteingne un point plus bas
                newz = Result.getValue(currentrow, currentcol)
                if newz <= prev_z:
                    intheraster = False

            z = min(prev_z, newz)
            Result.setValue(currentrow, currentcol, z)
            prev_z = z

            # On cherche le prochain point à partir du flow direction
            direction = flowdir.getValue(currentrow, currentcol)
            if (direction == 1):
                currentcol = currentcol + 1

            if (direction == 2):
                currentcol = currentcol + 1
                currentrow = currentrow + 1

            if (direction == 4):
                currentrow = currentrow + 1

            if (direction == 8):
                currentcol = currentcol - 1
                currentrow = currentrow + 1

            if (direction == 16):
                currentcol = currentcol - 1

            if (direction == 32):
                currentcol = currentcol - 1
                currentrow = currentrow - 1

            if (direction == 64):
                currentrow = currentrow - 1

            if (direction == 128):
                currentcol = currentcol + 1
                currentrow = currentrow - 1

            # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters
            if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
                intheraster = False
            elif (flowdir.getValue(currentrow, currentcol) != 1
                  and flowdir.getValue(currentrow, currentcol) != 2
                  and flowdir.getValue(currentrow, currentcol) != 4
                  and flowdir.getValue(currentrow, currentcol) != 8
                  and flowdir.getValue(currentrow, currentcol) != 16
                  and flowdir.getValue(currentrow, currentcol) != 32
                  and flowdir.getValue(currentrow, currentcol) != 64
                  and flowdir.getValue(currentrow, currentcol) != 128):
                intheraster = False
            if dem.getValue(currentrow, currentcol) == dem.nodata:
                intheraster = False
            if intheraster:
                if (Result.getValue(currentrow, currentcol) != -255):
                    # Atteinte d'un confluent
                    confluence = True

    Result.save()

    return
def execute_CreateZone(r_flowdir, str_lakes, r_slope, minslope, str_frompoint,
                       distance, bufferw, str_zonesfolder, messages):

    str_segments = str_zonesfolder + "\\segments"
    str_linesegments = str_zonesfolder + "\\line_segments.shp"
    str_bufferedsegments = str_zonesfolder + "\\buff_segments.shp"

    save_sourcepoints = str_zonesfolder + "\\sourcepoints.shp"

    str_r_lakes = str_zonesfolder + "\\r_lakes"

    flowdir = RasterIO(r_flowdir)
    if r_slope is not None:
        slope = RasterIO(r_slope)
        try:
            flowdir.checkMatch(slope)

        except Exception as e:
            messages.addErrorMessage(e.message)
    else:
        slope = None

    # Conversion des lacs en raster et copie
    arcpy.env.snapRaster = flowdir.raster
    arcpy.env.outputCoordinateSystem = flowdir.raster.spatialReference
    arcpy.env.extent = flowdir.raster
    arcpy.PolygonToRaster_conversion(str_lakes,
                                     arcpy.Describe(str_lakes).OIDFieldName,
                                     str_r_lakes,
                                     cellsize=flowdir.raster)
    lakes = RasterIO(arcpy.Raster(str_r_lakes))
    arcpy.CopyFeatures_management(str_lakes, str_zonesfolder + "\\lakes.shp")
    str_lakes = str_zonesfolder + "\\lakes.shp"
    arcpy.AddGeometryAttributes_management(str_lakes, "EXTENT")

    ### Début du traitement perrmettant d'identifier les segments (sous forme de raster) ###

    raster_segments = RasterIO(r_flowdir, str_segments, int, -255)

    # numérotation des segments
    segnumber = 0

    lakes_bci = {}
    toclip = {}
    inputpoints = {}

    # Pour chaque point de départ
    frompointcursor = arcpy.da.SearchCursor(str_frompoint, ["SHAPE@", "OID@"])
    for frompoint in frompointcursor:

        # On prend l'objet géométrique (le point) associé à la ligne dans la table
        frompointshape = frompoint[0].firstPoint

        # Nouvelle rivière : on change de segment
        segnumber += 1

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(frompointshape.X)
        currentrow = flowdir.YtoRow(frompointshape.Y)

        # Tests de sécurité pour s'assurer que le point de départ est à l'intérieurs des rasters
        intheraster = True
        if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
            intheraster = False
        elif (flowdir.getValue(currentrow, currentcol) != 1
              and flowdir.getValue(currentrow, currentcol) != 2
              and flowdir.getValue(currentrow, currentcol) != 4
              and flowdir.getValue(currentrow, currentcol) != 8
              and flowdir.getValue(currentrow, currentcol) != 16
              and flowdir.getValue(currentrow, currentcol) != 32
              and flowdir.getValue(currentrow, currentcol) != 64
              and flowdir.getValue(currentrow, currentcol) != 128):
            intheraster = False

        listpointsflowpath = []
        totaldistance = 0
        currentdistance = 0
        inlake = True
        # True si la rivière (depuis le point de départ jusqu'au confluent) est composée d'au moins deux segments
        dividedriver = False
        # listtomerged contient la liste des segments trop courts, qui doivent être fusionnés avec segment précédent
        listtomerged = []

        # Pour chaque cellule en suivant l'écoulement
        while (intheraster):

            waslake = inlake

            inlake = False
            lakevalue = lakes.getValue(currentrow, currentcol)

            inlake = (lakevalue != lakes.nodata)

            if not (inlake and waslake):
                # Distance parcourue depuis le début du segment
                totaldistance = totaldistance + currentdistance

            slope_criteria = True
            if slope is not None:
                slope_criteria = slope.getValue(currentrow,
                                                currentcol) > minslope

            # Test si on arrive à un lac
            if inlake and not waslake:
                # Segment trop court si de longueur inférieure à 30% de la distance voullue
                # Le segment doit être alors fusionné avec le segment précédent (qui existe uniquement si dividedriver = True)
                # ajout de l'info de clipper ensuite également
                coordX = flowdir.ColtoX(currentcol)
                coordY = flowdir.RowtoY(currentrow)

                fieldidlakes = arcpy.Describe(str_lakes).OIDFieldName
                shplakes = arcpy.da.SearchCursor(str_lakes, [
                    "SHAPE@", "EXT_MIN_X", "EXT_MAX_X", "EXT_MIN_Y",
                    "EXT_MAX_Y", fieldidlakes
                ])
                for shplake in shplakes:
                    if shplake[0].contains(arcpy.Point(coordX, coordY)):
                        lakes_bci[segnumber] = shplakes[5]
                        distXmin = abs(coordX - shplake[1])
                        distXmax = abs(coordX - shplake[2])
                        distYmin = abs(coordY - shplake[3])
                        distYmax = abs(coordY - shplake[4])
                        mini = min(distXmin, distXmax, distYmin, distYmax)
                        if mini == distXmin:
                            toclip[segnumber] = ["Xmax", shplake[1]]
                            messages.addMessage(
                                str(segnumber) + " Xmax " + str(shplake[1]))
                        if mini == distXmax:
                            toclip[segnumber] = ["Xmin", shplake[2]]
                            messages.addMessage(
                                str(segnumber) + " Xmin " + str(shplake[2]))
                        if mini == distYmin:
                            toclip[segnumber] = ["Ymax", shplake[3]]
                            messages.addMessage(
                                str(segnumber) + " Ymax " + str(shplake[3]))
                        if mini == distYmax:
                            toclip[segnumber] = ["Ymin", shplake[4]]
                            messages.addMessage(
                                str(segnumber) + " Ymin " + str(shplake[4]))
                if totaldistance < 0.3 * distance and dividedriver:
                    if segnumber in toclip:
                        toclip[segnumber - 1] = toclip.pop(segnumber)
                    listtomerged.append(segnumber)
                totaldistance = 0
                segnumber += 1
                dividedriver = False

            elif totaldistance > distance and slope_criteria:
                # Test si on a parcouru la distance voullue
                totaldistance = 0
                segnumber += 1
                dividedriver = True

            if not inlake:
                # On conseerve une liste des points traités, avec leur numéro de segment
                currentpoint = pointflowpath()
                currentpoint.row = currentrow
                currentpoint.col = currentcol
                currentpoint.X = flowdir.ColtoX(currentcol)
                currentpoint.Y = flowdir.RowtoY(currentrow)
                currentpoint.distance = totaldistance
                currentpoint.segnumber = segnumber
                currentpoint.frompointid = frompoint[1]
                listpointsflowpath.append(currentpoint)

            # On cherche le prochain point à partir du flow direction
            direction = flowdir.getValue(currentrow, currentcol)
            if (direction == 1):
                currentcol = currentcol + 1
                currentdistance = flowdir.raster.meanCellWidth
            if (direction == 2):
                currentcol = currentcol + 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)
            if (direction == 4):
                currentrow = currentrow + 1
                currentdistance = flowdir.raster.meanCellHeight
            if (direction == 8):
                currentcol = currentcol - 1
                currentrow = currentrow + 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)
            if (direction == 16):
                currentcol = currentcol - 1
                currentdistance = flowdir.raster.meanCellWidth
            if (direction == 32):
                currentcol = currentcol - 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)
            if (direction == 64):
                currentrow = currentrow - 1
                currentdistance = flowdir.raster.meanCellHeight
            if (direction == 128):
                currentcol = currentcol + 1
                currentrow = currentrow - 1
                currentdistance = math.sqrt(flowdir.raster.meanCellWidth *
                                            flowdir.raster.meanCellWidth +
                                            flowdir.raster.meanCellHeight *
                                            flowdir.raster.meanCellHeight)

            # Tests de sécurité pour s'assurer que l'on ne sorte pas des rasters
            if currentcol < 0 or currentcol >= flowdir.raster.width or currentrow < 0 or currentrow >= flowdir.raster.height:
                intheraster = False
            elif (flowdir.getValue(currentrow, currentcol) != 1
                  and flowdir.getValue(currentrow, currentcol) != 2
                  and flowdir.getValue(currentrow, currentcol) != 4
                  and flowdir.getValue(currentrow, currentcol) != 8
                  and flowdir.getValue(currentrow, currentcol) != 16
                  and flowdir.getValue(currentrow, currentcol) != 32
                  and flowdir.getValue(currentrow, currentcol) != 64
                  and flowdir.getValue(currentrow, currentcol) != 128):
                intheraster = False

            if intheraster:
                confluence_seg = raster_segments.getValue(
                    currentrow, currentcol)
                if (confluence_seg != -255):
                    # Atteinte d'un confluent déjà traité

                    # Si le segment dans lequel on arrive est limité par un lac, le confluent peut l'être aussi
                    # On copie l'item toclip pour limiter l'étendu de la zone
                    # par contre on garde l'élévation à -999 (hfix sera le résultat de la simulation du cours d'eau confluent)
                    if confluence_seg in listtomerged:
                        confluence_seg -= 1
                    if confluence_seg in toclip:
                        clipitem = list(toclip[confluence_seg])
                        toclip[segnumber] = clipitem

                    if totaldistance < 0.3 * distance and dividedriver:
                        # Segment trop court si de longueur inférieure à 30% de la distance voullue
                        # Le segment doit être alors fusionné avec le segment précédent (qui existe uniquement si dividedriver = True)
                        listtomerged.append(segnumber)
                        if segnumber in toclip:
                            toclip[segnumber - 1] = toclip.pop(segnumber)

                    intheraster = False

        # Pour chaque point traité le long de l'écoulement
        for currentpoint in listpointsflowpath:
            # Si c'est un point d'un segment trop court, on remplace le numéro du segment par le numéro du segment précédent
            if currentpoint.segnumber in listtomerged:
                currentpoint.segnumber -= 1
            # On enregistre le point
            raster_segments.setValue(currentpoint.row, currentpoint.col,
                                     currentpoint.segnumber)
            if currentpoint.segnumber not in inputpoints:
                newpoint = pointflowpath()
                newpoint.type = "main"
                newpoint.frompointid = currentpoint.frompointid
                # Coordonnées du point source
                newpoint.X = currentpoint.X
                newpoint.Y = currentpoint.Y

                inputpoints[currentpoint.segnumber] = newpoint

    raster_segments.save()

    ### Fin du traitement perrmettant d'identifier les segments ###

    ### Transformation du raster des segments en zones ####

    # Transformation en polyline
    tmp_segments = arcpy.env.scratchWorkspace + "\\tmpsegments.shp"
    arcpy.RasterToPolyline_conversion(str_segments, tmp_segments)
    arcpy.Dissolve_management(tmp_segments, str_linesegments, "GRID_CODE")
    arcpy.Delete_management(tmp_segments)

    # Création de la zone tampon
    # Harcoded : buffer longitudinal de 1/10 de l'extension latérale (obtenue par Euclidienne Allocation)
    tmp_segmentsbuf = arcpy.env.scratchWorkspace + "\\tmpsegments_buf.shp"
    arcpy.Buffer_analysis(str_linesegments, tmp_segmentsbuf, bufferw / 10.)
    segalloc = arcpy.sa.EucAllocation(raster_segments.raster, bufferw)
    arcpy.RasterToPolygon_conversion(segalloc, tmp_segments)
    arcpy.AddField_management(tmp_segments, "GRID_CODE", "LONG")
    arcpy.CalculateField_management(tmp_segments, "GRID_CODE", "!GRIDCODE!",
                                    "PYTHON_9.3")
    tmp_segments2 = arcpy.env.scratchWorkspace + "\\tmpsegments2.shp"
    arcpy.Merge_management([tmp_segmentsbuf, tmp_segments], tmp_segments2)
    arcpy.Dissolve_management(tmp_segments2,
                              str_bufferedsegments, ["GRID_CODE"],
                              multi_part="SINGLE_PART")

    arcpy.Delete_management(tmp_segments)
    arcpy.Delete_management(tmp_segments2)

    arcpy.Delete_management(str_lakes)

    # Création de la zone pour chaque segment
    arcpy.CreateFeatureclass_management(
        str_zonesfolder,
        "polyzones.shp",
        "POLYGON",
        str_bufferedsegments,
        spatial_reference=flowdir.raster.spatialReference)
    polyzones = str_zonesfolder + "\\polyzones.shp"
    arcpy.AddField_management(polyzones, "Lake_ID", "LONG")

    cursor = arcpy.da.InsertCursor(polyzones,
                                   ["GRID_CODE", "SHAPE@", "Lake_ID"])

    segmentscursor = arcpy.da.UpdateCursor(str_bufferedsegments,
                                           ["GRID_CODE", "SHAPE@"])
    for segment in segmentscursor:
        Xmin = segment[1].extent.XMin
        Ymin = segment[1].extent.YMin
        Xmax = segment[1].extent.XMax
        Ymax = segment[1].extent.YMax
        if segment[0] in toclip:

            if toclip[segment[0]][0] == "Xmin":
                Xmin = max(toclip[segment[0]][1], Xmin)
            if toclip[segment[0]][0] == "Xmax":
                Xmax = min(toclip[segment[0]][1], Xmax)
            if toclip[segment[0]][0] == "Ymin":
                Ymin = max(toclip[segment[0]][1], Ymin)
            if toclip[segment[0]][0] == "Ymax":
                Ymax = min(toclip[segment[0]][1], Ymax)

        segmentscursor.updateRow(segment)

        array = arcpy.Array([
            arcpy.Point(Xmin, Ymin),
            arcpy.Point(Xmin, Ymax),
            arcpy.Point(Xmax, Ymax),
            arcpy.Point(Xmax, Ymin)
        ])
        polygon = arcpy.Polygon(array)

        if segment[0] in lakes_bci:
            lakeid = lakes_bci[segment[0]]
        else:
            lakeid = -999

        cursor.insertRow([segment[0], polygon, lakeid])

    del cursor
    del segmentscursor

    arcpy.CreateFeatureclass_management(
        os.path.dirname(save_sourcepoints),
        os.path.basename(save_sourcepoints),
        "POINT",
        spatial_reference=flowdir.raster.spatialReference)
    arcpy.AddField_management(save_sourcepoints, "ZoneID", "LONG")
    arcpy.AddField_management(save_sourcepoints, "fpid", "LONG")

    pointcursor = arcpy.da.InsertCursor(save_sourcepoints,
                                        ["ZoneID", "fpid", "SHAPE@XY"])
    for pointkey in inputpoints:
        pointcursor.insertRow([
            pointkey, inputpoints[pointkey].frompointid,
            (inputpoints[pointkey].X, inputpoints[pointkey].Y)
        ])
    del pointcursor

    return
Exemple #17
0
def execute_LinearInterpolationWithPriority(r_flowdir,
                                            str_frompoint,
                                            r_values,
                                            str_results,
                                            messages,
                                            language="FR"):

    # Chargement des fichiers
    flowdir = RasterIO(r_flowdir)
    valuesatcs = RasterIO(r_values)
    try:
        flowdir.checkMatch(valuesatcs)
    except Exception as e:
        messages.addErrorMessage(e.message)

    trees = build_trees(flowdir, str_frompoint, tointerpolate=valuesatcs)

    # Find how to interpolate
    # Interpolation can not be done in this first run through the trees because the totaldistance must be calculated first
    for tree in trees:
        totaldistance = 0

        datacs_down = None
        for segment in tree.treesegments():
            for cs in segment.get_profile():
                if cs.tointerpolate != valuesatcs.nodata:
                    datacs_down = cs

                bestcsup = None
                for datacs_up in tree.points_up_with_data(
                        segment, cs, "tointerpolate", valuesatcs.nodata):
                    if datacs_down is not None:
                        # a downstream point exists: looking for the upstream point with the closest value
                        if bestcsup is None or (abs(datacs_down.tointerpolate -
                                                    datacs_up.tointerpolate) <
                                                abs(datacs_down.tointerpolate -
                                                    bestcsup.tointerpolate)):
                            bestcsup = datacs_up
                    else:
                        # a downstream point does not exist: looking for the upstream point with the highest value
                        if bestcsup is None or (datacs_up.tointerpolate >
                                                bestcsup.tointerpolate):
                            bestcsup = datacs_up

                cs.datacs_up = bestcsup
                if (datacs_down is not None) and (datacs_down.datacs_up
                                                  == cs.datacs_up):
                    # general case
                    cs.datacs_down = datacs_down
                else:
                    # special case at confluence, the local cs in a narrow steam, must be extrapolated from the upstream data
                    # Or, the cs is downstream the most downstream data point
                    cs.datacs_down = None

                totaldistance += cs.dist
                cs.totaldist = totaldistance

    # Calculating the interpolations and saving the results
    Result = RasterIO(r_values, str_results, float, -255)
    for tree in trees:
        for segment in tree.treesegments():
            for cs in segment.get_profile():
                if cs.datacs_down is None:
                    # extrapolation from upstream
                    cs.interpolated = cs.datacs_up.tointerpolate
                else:
                    if cs.datacs_up is None:
                        # extrapolation from downstream
                        cs.interpolated = cs.datacs_down.tointerpolate
                    else:
                        # interpolation
                        cs.interpolated = (cs.totaldist - cs.datacs_down.totaldist) \
                                          * (cs.datacs_up.tointerpolate - cs.datacs_down.tointerpolate) \
                                          / (cs.datacs_up.totaldist - cs.datacs_down.totaldist) \
                                          + cs.datacs_down.tointerpolate
                Result.setValue(cs.row, cs.col, cs.interpolated)

    Result.save()

    return
Exemple #18
0
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
Exemple #19
0
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