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 #2
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 #3
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_DefBCI(r_flowdir, r_flowacc, distoutput, percent, str_zonesfolder,
                   r_dem, r_width, r_zbed, r_manning, r_mask, str_outputfolder,
                   messages):

    save_inbci = str_zonesfolder + "\\inbci.shp"
    save_outbci = str_zonesfolder + "\\outbci.shp"

    # Chargement des fichiers
    flowdir = RasterIO(r_flowdir)
    flowacc = RasterIO(r_flowacc)
    dem = RasterIO(r_dem)

    try:
        flowdir.checkMatch(flowacc)
        flowdir.checkMatch(dem)
    except Exception as e:
        messages.addErrorMessage(e.message)

    # Création d'un nouveau fichier de zones en prenant les enveloppes
    zones = str_zonesfolder + "\\envelopezones.shp"
    arcpy.FeatureEnvelopeToPolygon_management(
        str_zonesfolder + "\\polyzones.shp", zones)

    # Clip du DEM

    zonesscursor = arcpy.da.SearchCursor(zones, ["GRID_CODE", "SHAPE@"])
    for zoneshp in zonesscursor:

        Xmin = zoneshp[1].extent.XMin
        Ymin = zoneshp[1].extent.YMin
        Xmax = zoneshp[1].extent.XMax
        Ymax = zoneshp[1].extent.YMax
        envelope = str(Xmin) + " " + str(Ymin) + " " + str(Xmax) + " " + str(
            Ymax)
        arcpy.Clip_management(dem.raster, envelope,
                              str_zonesfolder + "\\zone" + str(zoneshp[0]))

    # Listes des points source et des points de sortie
    listinputpoints = []
    listoutputpoints = []

    # Lectures des points source pour chaque zone
    sourcepointcursor = arcpy.da.SearchCursor(
        str_zonesfolder + "\\sourcepoints.shp", ["SHAPE@", "ZoneID", "fpid"])
    for sourcepoint in sourcepointcursor:
        newpoint = pointflowpath()
        newpoint.type = "main"
        newpoint.frompointid = sourcepoint[2]
        # Coordonnées du point source
        newpoint.X = sourcepoint[0].firstPoint.X
        newpoint.Y = sourcepoint[0].firstPoint.Y
        # Raster de la zone
        newpoint.numzone = sourcepoint[1]
        # Valeur du flow accumulation
        col = flowacc.XtoCol(newpoint.X)
        row = flowacc.YtoRow(newpoint.Y)
        newpoint.flowacc = flowacc.getValue(row, col)

        listinputpoints.append(newpoint)

    ### Début de traitement pour la détection des points de sortie et des points sources latéraux ###

    listlateralinputpoints = []

    # Pour chaque raster, on parcourt l'écoulement à partir du point source
    for mainpoint in listinputpoints:

        # Raster de la zone correspondante au point source
        localraster = RasterIO(
            arcpy.Raster(str_zonesfolder + r"\zone" + str(mainpoint.numzone)))

        # Conversion des coordonnées
        currentcol = flowdir.XtoCol(mainpoint.X)
        currentrow = flowdir.YtoRow(mainpoint.Y)
        localcol = localraster.XtoCol(mainpoint.X)
        localrow = localraster.YtoRow(mainpoint.Y)

        currentflowacc = flowacc.getValue(currentrow, currentcol)
        mainpoint.flowacc = currentflowacc
        lastflowacc = currentflowacc

        # Parcours de l'écoulement
        intheraster = True
        while (intheraster):

            prevcol = currentcol
            prevrow = currentrow

            currentflowacc = flowacc.getValue(currentrow, currentcol)

            if 100. * float(currentflowacc -
                            lastflowacc) / float(lastflowacc) >= percent:
                newpoint = pointflowpath()
                newpoint.type = "lateral"
                newpoint.frompointid = mainpoint.frompointid
                # Coordonnées du point source
                newpoint.X = flowdir.ColtoX(currentcol)
                newpoint.Y = flowdir.RowtoY(currentrow)
                # Raster de la zone
                newpoint.numzone = mainpoint.numzone
                # Valeur du flow accumulation
                newpoint.flowacc = currentflowacc
                lastflowacc = currentflowacc

                listlateralinputpoints.append(newpoint)

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

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

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

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

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

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

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

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

            if localcol < 0 or localcol >= localraster.raster.width or localrow < 0 or localrow >= localraster.raster.height:
                intheraster = False
            elif localraster.getValue(localrow,
                                      localcol) == localraster.nodata:
                intheraster = False

        # On enregistre un point de sortie au dernier point traité avant de sortir de la zone
        newpoint = pointflowpath()
        newpoint.numzone = mainpoint.numzone
        newpoint.X = flowdir.ColtoX(prevcol)
        newpoint.Y = flowdir.RowtoY(prevrow)

        # Il est nécessaire d'enregistrer le côté du raster par lequel on sort.
        # Ceci est fait en regardant la distance entre le dernier point traité et les coordonnées maximales de la zone
        # Le côté de sortie est le côté pour lequel cette distance est minimum
        distside = min(newpoint.X - localraster.raster.extent.XMin,
                       localraster.raster.extent.XMax - newpoint.X,
                       newpoint.Y - localraster.raster.extent.YMin,
                       localraster.raster.extent.YMax - newpoint.Y)
        if distside == newpoint.X - localraster.raster.extent.XMin:
            newpoint.side = "W"
        if distside == localraster.raster.extent.XMax - newpoint.X:
            newpoint.side = "E"
        if distside == newpoint.Y - localraster.raster.extent.YMin:
            newpoint.side = "S"
        if distside == localraster.raster.extent.YMax - newpoint.Y:
            newpoint.side = "N"
        listoutputpoints.append(newpoint)

    listinputpoints.extend(listlateralinputpoints)
    ### Fin de traitement pour la détection des points de sortie et des points sources latéraux ###

    ### Début de traitement pour la configuration des fenêtres de sortie ###

    # Pour chaque point de sortie
    for point in listoutputpoints:
        raster = RasterIO(
            arcpy.Raster(str_zonesfolder + r"\zone" + str(point.numzone)))
        colinc = 0
        rowinc = 0
        distinc = 0
        point.side2 = "0"
        point.lim3 = 0
        point.lim4 = 0
        # Selon le coté de sortie, on progressera horizontalement ou verticalement
        if point.side == "W" or point.side == "E":
            rowinc = 1
            distinc = raster.raster.meanCellHeight
        else:
            colinc = 1
            distinc = raster.raster.meanCellWidth
        currentcol = raster.XtoCol(point.X)
        currentrow = raster.YtoRow(point.Y)
        distance = 0
        # On progresse sur dans une direction jusqu'à sortir du raster ou jusqu'à ce que la distance voullue soit attente
        while (not (currentcol < 0 or currentcol >= raster.raster.width or currentrow < 0 or currentrow >= raster.raster.height)) \
                and raster.getValue(currentrow,currentcol) != raster.nodata and distance < distoutput/2:
            distance += distinc
            currentrow += rowinc
            currentcol += colinc
        # On prends les coordonnées avant de sortir du raster
        currentrow -= rowinc
        currentcol -= colinc
        if point.side == "W" or point.side == "E":
            point.lim1 = raster.RowtoY(currentrow)
        else:
            point.lim1 = raster.ColtoX(currentcol)
        # Si la procédure s'est arrêtée parce qu'on est sorti du raster, on tourne de 90 degrés et on continue
        if distance < distoutput / 2:
            distance -= distinc
            if point.side == "W":
                colinc = 1
                rowinc = 0
                distinc = raster.raster.meanCellWidth
                point.lim3 = raster.raster.extent.XMin + (
                    currentcol + 0.5) * raster.raster.meanCellWidth
            elif point.side == "E":
                colinc = -1
                rowinc = 0
                distinc = raster.raster.meanCellWidth
                point.lim3 = raster.raster.extent.XMin + (
                    currentcol + 0.5) * raster.raster.meanCellWidth

            elif point.side == "N":
                rowinc = 1
                colinc = 0
                distinc = raster.raster.meanCellHeight
                point.lim3 = max(
                    raster.raster.extent.YMin, raster.raster.extent.YMax -
                    (currentrow + 1) * raster.raster.meanCellHeight
                ) + 0.5 * raster.raster.meanCellHeight
            elif point.side == "S":
                rowinc = -1
                colinc = 0
                distinc = raster.raster.meanCellHeight
                point.lim3 = max(
                    raster.raster.extent.YMin, raster.raster.extent.YMax -
                    (currentrow + 1) * raster.raster.meanCellHeight
                ) + 0.5 * raster.raster.meanCellHeight
            # On progresse à nouveau jusqu'à sortir du raster ou jusqu'à ce que la distance voullue soit attente
            while (not (currentcol < 0 or currentcol >= raster.raster.width or currentrow < 0 or currentrow >= raster.raster.height)) \
                    and raster.getValue(currentrow, currentcol) != raster.nodata and distance < distoutput / 2:
                distance += distinc
                currentrow += rowinc
                currentcol += colinc
            currentrow -= rowinc
            currentcol -= colinc
            # On cherche sur quel coté on est après avoir tourné de 90 degrés
            if point.side == "W" or point.side == "E":
                point.side2 = "S"
                point.lim4 = raster.raster.extent.XMin + (
                    currentcol + 0.5) * raster.raster.meanCellWidth
            else:
                point.side2 = "E"
                point.lim4 = max(
                    raster.raster.extent.YMin, raster.raster.extent.YMax -
                    (currentrow + 1) * raster.raster.meanCellHeight
                ) + 0.5 * raster.raster.meanCellHeight

        # On recommence toute la procédure de l'autre côté du point de sortie
        colinc = 0
        rowinc = 0
        distinc = 0
        if point.side == "W" or point.side == "E":
            rowinc = -1
            distinc = raster.raster.meanCellHeight
        else:
            colinc = -1
            distinc = raster.raster.meanCellWidth
        currentcol = raster.XtoCol(point.X)
        currentrow = raster.YtoRow(point.Y)
        distance = 0
        while (not (currentcol < 0 or currentcol >= raster.raster.width or currentrow < 0 or currentrow >= raster.raster.height)) \
                and raster.getValue(currentrow, currentcol) != raster.nodata and distance < distoutput / 2:
            distance += distinc
            currentrow += rowinc
            currentcol += colinc
        currentrow -= rowinc
        currentcol -= colinc
        if point.side == "W" or point.side == "E":
            point.lim2 = max(
                raster.raster.extent.YMin, raster.raster.extent.YMax -
                (currentrow + 1) * raster.raster.meanCellHeight
            ) + 0.5 * raster.raster.meanCellHeight
        else:
            point.lim2 = raster.raster.extent.XMin + (
                currentcol + 0.5) * raster.raster.meanCellWidth
        # Si la procédure s'est arrêtée parce qu'on est sorti du raster, on tourne de 90 degrés et on continue
        if distance < distoutput / 2:
            distance -= distinc
            if point.side == "W":
                colinc = 1
                rowinc = 0
                distinc = raster.raster.meanCellWidth
                point.lim3 = raster.raster.extent.XMin + (
                    currentcol + 0.5) * raster.raster.meanCellWidth
            elif point.side == "E":
                colinc = -1
                rowinc = 0
                distinc = raster.raster.meanCellWidth
                point.lim3 = raster.raster.extent.XMin + (
                    currentcol + 0.5) * raster.raster.meanCellWidth
            elif point.side == "N":
                rowinc = 1
                colinc = 0
                distinc = raster.raster.meanCellHeight
                point.lim3 = max(
                    raster.raster.extent.YMin, raster.raster.extent.YMax -
                    (currentrow + 1) * raster.raster.meanCellHeight
                ) + 0.5 * raster.raster.meanCellHeight
            elif point.side == "S":
                rowinc = -1
                colinc = 0
                distinc = raster.raster.meanCellHeight
                point.lim3 = max(
                    raster.raster.extent.YMin, raster.raster.extent.YMax -
                    (currentrow + 1) * raster.raster.meanCellHeight
                ) + 0.5 * raster.raster.meanCellHeight
            while (not (currentcol < 0 or currentcol >= raster.raster.width or currentrow < 0 or currentrow >= raster.raster.height)) \
                and raster.getValue(currentrow, currentcol) != raster.nodata and distance < distoutput / 2:
                distance += distinc
                currentrow += rowinc
                currentcol += colinc
            currentrow -= rowinc
            currentcol -= colinc
            if point.side == "W" or point.side == "E":
                point.side2 = "N"
                point.lim4 = raster.raster.extent.XMin + (
                    currentcol + 0.5) * raster.raster.meanCellWidth
            else:
                point.side2 = "W"
                point.lim4 = max(
                    raster.raster.extent.YMin, raster.raster.extent.YMax -
                    (currentrow + 1) * raster.raster.meanCellHeight
                ) + 0.5 * raster.raster.meanCellHeight

    ### Fin du traitement pour la configuration des fenêtres de sortie ###

    # Création des shapefiles inbci et outbci, avec les champs nécessaires
    arcpy.CreateFeatureclass_management(
        os.path.dirname(save_inbci),
        os.path.basename(save_inbci),
        "POINT",
        spatial_reference=flowdir.raster.spatialReference)
    arcpy.AddField_management(save_inbci, "zoneid", "LONG")
    arcpy.AddField_management(save_inbci, "flowacc", "LONG")
    arcpy.AddField_management(save_inbci, "type", "TEXT")
    arcpy.AddField_management(save_inbci, "fpid", "LONG")
    arcpy.CreateFeatureclass_management(
        os.path.dirname(save_outbci),
        os.path.basename(save_outbci),
        "POINT",
        spatial_reference=flowdir.raster.spatialReference)
    arcpy.AddField_management(save_outbci, "zoneid", "LONG")
    arcpy.AddField_management(save_outbci, "side", "TEXT", field_length=1)
    arcpy.AddField_management(save_outbci, "lim1", "LONG")
    arcpy.AddField_management(save_outbci, "lim2", "LONG")
    arcpy.AddField_management(
        save_outbci,
        "side2",
        "TEXT",
        field_length=1,
    )
    arcpy.AddField_management(save_outbci, "lim3", "LONG")
    arcpy.AddField_management(save_outbci, "lim4", "LONG")

    # Enregistrement dans les shapefiles des informations contenues dans les listes
    pointcursor = arcpy.da.InsertCursor(
        save_inbci, ["zoneid", "flowacc", "type", "fpid", "SHAPE@XY"])
    for point in listinputpoints:
        pointcursor.insertRow([
            point.numzone, point.flowacc, point.type, point.frompointid,
            (point.X, point.Y)
        ])
    pointcursor = arcpy.da.InsertCursor(save_outbci, [
        "zoneid", "side", "lim1", "lim2", "side2", "lim3", "lim4", "SHAPE@XY"
    ])
    for point in listoutputpoints:
        pointcursor.insertRow([
            point.numzone, point.side, point.lim1, point.lim2, point.side2,
            point.lim3, point.lim4, (point.X, point.Y)
        ])

    del pointcursor

    # Création des fichiers .bci à partir des information du fichier inbci.shp

    bcipointcursor = arcpy.da.SearchCursor(
        save_inbci, ["SHAPE@", "zoneid", "flowacc", "type"])
    dictsegmentsin = {}
    for point in bcipointcursor:
        if point[1] not in dictsegmentsin:
            dictsegmentsin[point[1]] = []
        dictsegmentsin[point[1]].append(point)

    for segment in dictsegmentsin.values():
        for point in sorted(segment, key=lambda q: q[2]):
            if point[3] == "main":
                latnum = 0

                pointshape = point[0].firstPoint

                # Création du fichier
                newfile = str_outputfolder + "\\zone" + str(point[1]) + ".bci"

                # Enregistrement des coordonnées pour le point source
                filebci = open(newfile, 'w')
                filebci.write("P\t" + str(int(pointshape.X)) + "\t" +
                              str(int(pointshape.Y)) + "\tQVAR\tzone" +
                              str(point[1]) + "\n")
                filebci.close()

            if point[3] == "lateral":
                pointshape = point[0].firstPoint

                latnum += 1
                newfile = str_outputfolder + "\\zone" + str(point[1]) + ".bci"

                # Enregistrement des coordonnées et du débit pour le point source
                filebci = open(newfile, 'a')
                filebci.write("P\t" + str(int(pointshape.X)) + "\t" +
                              str(int(pointshape.Y)) + "\tQVAR\tzone" +
                              str(point[1]) + "_" + str(latnum) + "\n")
                filebci.close()

    # Ajout de la zone de sortie au .bci
    bcipointcursor = arcpy.da.SearchCursor(
        save_outbci,
        ["zoneid", "side", "lim1", "lim2", "side2", "lim3", "lim4", "SHAPE@"])
    for point in bcipointcursor:
        newfile = str_outputfolder + "\\zone" + str(point[0]) + ".bci"
        filebci = open(newfile, 'a')
        filebci.write(point[1] + "\t" + str(point[2]) + "\t" + str(point[3]) +
                      "\tHVAR\thvar")
        if str(point[4]) != "0":
            filebci.write("\n" + str(point[4]) + "\t" + str(point[5]) + "\t" +
                          str(point[6]) + "\tHVAR\thvar")
        filebci.close()

    # Création des fichiers .par et conversion des rasters en fichiers ASCII (un par point source comme il n'y a qu'un seul point d'entrée par simulation)

    for segment in dictsegmentsin.values():
        for point in sorted(segment, key=lambda q: q[2]):

            if point[3] == "main":

                arcpy.Clip_management(
                    r_width, "#", str_zonesfolder + r"\wzone" + str(point[1]),
                    str_zonesfolder + "\\zone" + str(point[1]), "#", "NONE",
                    "MAINTAIN_EXTENT")
                arcpy.Clip_management(
                    r_zbed, "#", str_zonesfolder + r"\dzone" + str(point[1]),
                    str_zonesfolder + "\\zone" + str(point[1]), "#", "NONE",
                    "MAINTAIN_EXTENT")
                arcpy.Clip_management(
                    r_manning, "#",
                    str_zonesfolder + r"\nzone" + str(point[1]),
                    str_zonesfolder + "\\zone" + str(point[1]), "#", "NONE",
                    "MAINTAIN_EXTENT")

                arcpy.RasterToASCII_conversion(
                    str_zonesfolder + "\\zone" + str(point[1]),
                    str_outputfolder + "\\zone" + str(point[1]) + ".txt")
                arcpy.RasterToASCII_conversion(
                    str_zonesfolder + "\dzone" + str(point[1]),
                    str_outputfolder + "\\dzone" + str(point[1]) + ".txt")
                arcpy.RasterToASCII_conversion(
                    str_zonesfolder + "\wzone" + str(point[1]),
                    str_outputfolder + "\\wzone" + str(point[1]) + ".txt")

                arcpy.RasterToASCII_conversion(
                    str_zonesfolder + "\\nzone" + str(point[1]),
                    str_outputfolder + "\\nzone" + str(point[1]) + ".txt")
                arcpy.Delete_management(str_zonesfolder + r"\wzone" +
                                        str(point[1]))
                arcpy.Delete_management(str_zonesfolder + r"\dzone" +
                                        str(point[1]))
                arcpy.Delete_management(str_zonesfolder + r"\nzone" +
                                        str(point[1]))

                arcpy.Clip_management(
                    r_mask, "#", str_zonesfolder + r"\mzone" + str(point[1]),
                    str_zonesfolder + "\\zone" + str(point[1]), "#", "NONE",
                    "MAINTAIN_EXTENT")
                arcpy.RasterToASCII_conversion(
                    str_zonesfolder + "\mzone" + str(point[1]),
                    str_outputfolder + "\\mzone" + str(point[1]) + ".txt")
                arcpy.Delete_management(str_zonesfolder + r"\mzone" +
                                        str(point[1]))

    return