def aspectRatio(grid_input,
                grid_output,
                roads_input,
                built_input,
                seg_dist,
                seg_length,
                buffer_size,
                epsg,
                project_encoding,
                server_postgis,
                port_number,
                user_postgis,
                password_postgis,
                database_postgis,
                schema_postgis,
                path_time_log,
                format_vector='ESRI Shapefile',
                extension_vector=".shp",
                save_results_intermediate=False,
                overwrite=True):

    print(bold + yellow + "Début du calcul de l'indicateur Aspect Ratio." +
          endC + "\n")
    timeLine(path_time_log, "Début du calcul de l'indicateur Aspect Ratio : ")

    if debug >= 3:
        print(bold + green + "aspectRatio() : Variables dans la fonction" +
              endC)
        print(cyan + "aspectRatio() : " + endC + "grid_input : " +
              str(grid_input) + endC)
        print(cyan + "aspectRatio() : " + endC + "grid_output : " +
              str(grid_output) + endC)
        print(cyan + "aspectRatio() : " + endC + "roads_input : " +
              str(roads_input) + endC)
        print(cyan + "aspectRatio() : " + endC + "built_input : " +
              str(built_input) + endC)
        print(cyan + "aspectRatio() : " + endC + "seg_dist : " +
              str(seg_dist) + endC)
        print(cyan + "aspectRatio() : " + endC + "seg_length : " +
              str(seg_length) + endC)
        print(cyan + "aspectRatio() : " + endC + "buffer_size : " +
              str(buffer_size) + endC)
        print(cyan + "aspectRatio() : " + endC + "epsg : " + str(epsg) + endC)
        print(cyan + "aspectRatio() : " + endC + "project_encoding : " +
              str(project_encoding) + endC)
        print(cyan + "aspectRatio() : " + endC + "server_postgis : " +
              str(server_postgis) + endC)
        print(cyan + "aspectRatio() : " + endC + "port_number : " +
              str(port_number) + endC)
        print(cyan + "aspectRatio() : " + endC + "user_postgis : " +
              str(user_postgis) + endC)
        print(cyan + "aspectRatio() : " + endC + "password_postgis : " +
              str(password_postgis) + endC)
        print(cyan + "aspectRatio() : " + endC + "database_postgis : " +
              str(database_postgis) + endC)
        print(cyan + "aspectRatio() : " + endC + "schema_postgis : " +
              str(schema_postgis) + endC)
        print(cyan + "aspectRatio() : " + endC + "format_vector : " +
              str(format_vector) + endC)
        print(cyan + "aspectRatio() : " + endC + "extension_vector : " +
              str(extension_vector) + endC)
        print(cyan + "aspectRatio() : " + endC + "path_time_log : " +
              str(path_time_log) + endC)
        print(cyan + "aspectRatio() : " + endC +
              "save_results_intermediate : " + str(save_results_intermediate) +
              endC)
        print(cyan + "aspectRatio() : " + endC + "overwrite : " +
              str(overwrite) + endC)

    # Constantes liées aux données PostGIS et GRASS
    LOCATION = "LOCATION"
    MAPSET = "MAPSET"
    SUFFIX_SEGMENTED = "_segmented"

    if not os.path.exists(grid_output) or overwrite:

        ############################################
        ### Préparation générale des traitements ###
        ############################################

        if os.path.exists(grid_output):
            removeVectorFile(grid_output)

        temp_path = os.path.dirname(grid_output) + os.sep + "AspectRatio"
        file_name = os.path.splitext(os.path.basename(roads_input))[0]
        roads_segmented = temp_path + os.sep + file_name + SUFFIX_SEGMENTED + extension_vector

        if os.path.exists(temp_path):
            shutil.rmtree(temp_path)

        # Variables d'environnement spécifiques à GRASS
        gisbase = os.environ['GISBASE']
        gisdb = "GRASS_database"

        # Variables liées à GRASS permettant la construction de 'LOCATION' et 'MAPSET'
        xmin, xmax, ymin, ymax = getEmpriseFile(roads_input, format_vector)
        pixel_size_x, pixel_size_y = 1, 1

        #####################################
        ### Préparation géodatabase GRASS ###
        #####################################

        print(bold + cyan + "Préparation de la géodatabase GRASS :" + endC)
        timeLine(path_time_log, "    Préparation de la géodatabase GRASS : ")

        # Initialisation de la connexion à la géodatabase GRASS
        gisbase, gisdb, location, mapset = initializeGrass(
            temp_path, xmin, xmax, ymin, ymax, pixel_size_x, pixel_size_y,
            epsg, gisbase, gisdb, LOCATION, MAPSET, True, overwrite)

        ###################################################
        ### Division des routes en segments de x mètres ###
        ###################################################

        print(bold + cyan + "Segmentation des routes avec GRASS :" + endC)
        timeLine(path_time_log, "    Segmentation des routes avec GRASS : ")

        # Segmentation du jeu de données route en segments de x mètres
        splitGrass(roads_input, roads_segmented, seg_dist, format_vector,
                   overwrite)
        cleanGrass(temp_path, gisdb, save_results_intermediate)

        ###########################################
        ### Préparation base de données PostGIS ###
        ###########################################

        print(bold + cyan + "Préparation de la base de données PostGIS :" +
              endC)
        timeLine(path_time_log,
                 "    Préparation de la base de données PostGIS : ")

        # Création de la base de données PostGIS
        # Conflits avec autres indicateurs (Height of Roughness Elements / Terrain Roughness Class)
        createDatabase(database_postgis)

        # Import des fichiers shapes maille, bati et routes segmentées dans la base de données PostGIS
        table_name_maille = importVectorByOgr2ogr(database_postgis,
                                                  grid_input,
                                                  'ara_maille',
                                                  user_name=user_postgis,
                                                  password=password_postgis,
                                                  ip_host=server_postgis,
                                                  num_port=str(port_number),
                                                  schema_name=schema_postgis,
                                                  epsg=str(epsg),
                                                  codage=project_encoding)
        table_name_bati = importVectorByOgr2ogr(database_postgis,
                                                built_input,
                                                'ara_bati',
                                                user_name=user_postgis,
                                                password=password_postgis,
                                                ip_host=server_postgis,
                                                num_port=str(port_number),
                                                schema_name=schema_postgis,
                                                epsg=str(epsg),
                                                codage=project_encoding)
        table_name_routes_seg = importVectorByOgr2ogr(
            database_postgis,
            roads_segmented,
            'ara_routes_seg',
            user_name=user_postgis,
            password=password_postgis,
            ip_host=server_postgis,
            num_port=str(port_number),
            schema_name=schema_postgis,
            epsg=str(epsg),
            codage=project_encoding)

        # Connection à la base de données PostGIS et initialisation de 'cursor' (permet de récupérer des résultats de requêtes SQL pour les traiter en Python)
        connection = openConnection(database_postgis,
                                    user_postgis,
                                    password_postgis,
                                    server_postgis,
                                    str(port_number),
                                    schema_name=schema_postgis)
        cursor = connection.cursor()

        # Requête d'ajout de champ ID segment route dans la table routes_seg et création des index pour les shapes importés
        query_preparation = """
        ALTER TABLE %s ADD COLUMN id_seg serial;
        --CREATE INDEX IF NOT EXISTS routes_seg_geom_gist ON %s USING GIST (geom);
        --CREATE INDEX IF NOT EXISTS bati_geom_gist ON %s USING GIST (geom);
        --CREATE INDEX IF NOT EXISTS maille_geom_gist ON %s USING GIST (geom);
        """ % (table_name_routes_seg, table_name_routes_seg, table_name_bati,
               table_name_maille)
        if debug >= 2:
            print(query_preparation)
        executeQuery(connection, query_preparation)

        ##############################################################################
        ### Création des segments de y mètres perpendiculaires aux segments routes ###
        ##############################################################################

        print(bold + cyan +
              "Création des segments perpendiculaires aux routes :" + endC)
        timeLine(path_time_log,
                 "    Création des segments perpendiculaires aux routes : ")

        # Début de la construction de la requête de création des segments perpendiculaires
        query_seg_perp = "DROP TABLE IF EXISTS ara_seg_perp;\n"
        query_seg_perp += "CREATE TABLE ara_seg_perp (id_seg text, id_perp text, xR float, yR float, xP float, yP float, geom geometry);\n"
        query_seg_perp += "INSERT INTO ara_seg_perp VALUES\n"

        # Récupération de la liste des identifiants segments routes
        cursor.execute(
            "SELECT id_seg FROM %s GROUP BY id_seg ORDER BY id_seg;" %
            table_name_routes_seg)
        id_seg_list = cursor.fetchall()

        # Boucle sur les segments routes
        nb_seg = len(id_seg_list)
        treat_seg = 1
        for id_seg in id_seg_list:
            if debug >= 4:
                print(bold + "    Traitement du segment route : " + endC +
                      str(treat_seg) + "/" + str(nb_seg))

            id_seg = id_seg[0]

            # Table temporaire ne contenant qu'un segment route donné : ST_LineMerge(geom) permet de passer la géométrie de MultiLineString à LineString, pour éviter des problèmes de requêtes spatiales
            query_temp1_seg = "DROP TABLE IF EXISTS ara_temp1_seg;\n"
            query_temp1_seg += "CREATE TABLE ara_temp1_seg AS SELECT id_seg as id_seg, ST_LineMerge(geom) as geom FROM %s WHERE id_seg = %s;\n" % (
                table_name_routes_seg, id_seg)
            if debug >= 4:
                print(query_temp1_seg)
            executeQuery(connection, query_temp1_seg)

            # Récupération du nombre de sommets du segment route (utile pour les segments routes en courbe, permet de récupérer le dernier point du segment)
            cursor.execute("SELECT ST_NPoints(geom) FROM ara_temp1_seg;")
            nb_points = cursor.fetchone()

            # Récupération des coordonnées X et Y des points extrémités du segment route
            query_xR1 = "SELECT ST_X(geom) as X FROM (SELECT ST_AsText(ST_PointN(geom,1)) as geom FROM ara_temp1_seg) as toto;"
            cursor.execute(query_xR1)
            xR1 = cursor.fetchone()
            query_yR1 = "SELECT ST_Y(geom) as Y FROM (SELECT ST_AsText(ST_PointN(geom,1)) as geom FROM ara_temp1_seg) as toto;"
            cursor.execute(query_yR1)
            yR1 = cursor.fetchone()
            query_xR2 = "SELECT ST_X(geom) as X FROM (SELECT ST_AsText(ST_PointN(geom,%s)) as geom FROM ara_temp1_seg) as toto;" % (
                nb_points)
            cursor.execute(query_xR2)
            xR2 = cursor.fetchone()
            query_yR2 = "SELECT ST_Y(geom) as Y FROM (SELECT ST_AsText(ST_PointN(geom,%s)) as geom FROM ara_temp1_seg) as toto;" % (
                nb_points)
            cursor.execute(query_yR2)
            yR2 = cursor.fetchone()

            # Transformation des coordonnées X et Y des points extrémités du segment route en valeurs numériques
            xR1 = float(str(xR1)[1:-2])
            yR1 = float(str(yR1)[1:-2])
            xR2 = float(str(xR2)[1:-2])
            yR2 = float(str(yR2)[1:-2])
            if debug >= 4:
                print("      xR1 = " + str(xR1))
                print("      yR1 = " + str(yR1))
                print("      xR2 = " + str(xR2))
                print("      yR2 = " + str(yR2))

            # Calcul des delta X et Y entre les points extrémités du segment route
            dxR = xR1 - xR2
            dyR = yR1 - yR2
            if debug >= 4:
                print("      dxR = " + str(dxR))
                print("      dyR = " + str(dyR))
                print("\n")

            # Suppression des cas où le script créé des perpendiculaires tous les cm ! Bug lié à la segmentation des routes
            dist_R1_R2 = math.sqrt((abs(dxR)**2) + (abs(dyR)**2))
            if dist_R1_R2 >= (seg_dist / 2):

                # Calcul de l'angle (= gisement) entre le Nord et le segment route
                if dxR == 0 or dyR == 0:
                    if dxR == 0 and dyR > 0:
                        aR = 0
                    elif dxR > 0 and dyR == 0:
                        aR = 90
                    elif dxR == 0 and dyR < 0:
                        aR = 180
                    elif dxR < 0 and dyR == 0:
                        aR = 270
                else:
                    aR = math.degrees(math.atan(dxR / dyR))
                    if aR < 0:
                        aR = aR + 360
                if debug >= 4:
                    print("      aR = " + str(aR))

                # Calcul des angles (= gisements) entre le Nord et les 2 segments perpendiculaires au segment route
                aP1 = aR + 90
                if aP1 < 0:
                    aP1 = aP1 + 360
                if aP1 >= 360:
                    aP1 = aP1 - 360
                aP2 = aR - 90
                if aP2 < 0:
                    aP2 = aP2 + 360
                if aP2 >= 360:
                    aP2 = aP2 - 360
                if debug >= 4:
                    print("      aP1 = " + str(aP1))
                    print("      aP2 = " + str(aP2))

                # Calculs des coordonnées des nouveaux points à l'extrémité de chaque segment perpendiculaire pour le segment route sélectionné
                xP1 = xR1 + (seg_length * math.sin(math.radians(aP1)))
                yP1 = yR1 + (seg_length * math.cos(math.radians(aP1)))
                xP2 = xR1 + (seg_length * math.sin(math.radians(aP2)))
                yP2 = yR1 + (seg_length * math.cos(math.radians(aP2)))
                if debug >= 4:
                    print("      xP1 = " + str(xP1))
                    print("      yP1 = " + str(yP1))
                    print("      xP2 = " + str(xP2))
                    print("      yP2 = " + str(yP2))
                    print("\n")

                # Construction de la requête de création des 2 segments perpendiculaires pour le segment route sélectionné
                query_seg_perp += "    ('%s', '%s_perp1', %s, %s, %s, %s, 'LINESTRING(%s %s, %s %s)'),\n" % (
                    str(id_seg), str(id_seg), xR1, yR1, xP1, yP1, xR1, yR1,
                    xP1, yP1)
                query_seg_perp += "    ('%s', '%s_perp2', %s, %s, %s, %s, 'LINESTRING(%s %s, %s %s)'),\n" % (
                    str(id_seg), str(id_seg), xR1, yR1, xP2, yP2, xR1, yR1,
                    xP2, yP2)

            treat_seg += 1

        # Fin de la construction de la requête de création des segments perpendiculaires et exécution de cette requête
        query_seg_perp = query_seg_perp[:-2] + ";\n"  # Transformer la virgule de la dernière ligne SQL en point-virgule (pour terminer la requête)
        query_seg_perp += "ALTER TABLE ara_seg_perp ALTER COLUMN geom TYPE geometry(LINESTRING,%s) USING ST_SetSRID(geom,%s);\n" % (
            epsg, epsg)  # Mise à jour du système de coordonnées
        query_seg_perp += "CREATE INDEX IF NOT EXISTS seg_perp_geom_gist ON ara_seg_perp USING GIST (geom);\n"
        if debug >= 2:
            print(query_seg_perp)
        executeQuery(connection, query_seg_perp)

        ###################################################
        ### Intersect segments perpendiculaires et bâti ###
        ###################################################

        print(
            bold + cyan +
            "Intersect entre les segments perpendiculaires et les bâtiments :"
            + endC)
        timeLine(
            path_time_log,
            "    Intersect entre les segments perpendiculaires et les bâtiments : "
        )

        # Requête d'intersect entre les segments perpendiculaires et les bâtiments
        query_intersect = """
        DROP TABLE IF EXISTS ara_intersect_bati;
        CREATE TABLE ara_intersect_bati AS
            SELECT r.id_seg as id_seg, r.id_perp as id_perp, r.xR as xR, r.yR as yR, b.HAUTEUR as haut_bati, ST_Intersection(r.geom, b.geom) as geom
            FROM ara_seg_perp as r, %s as b
            WHERE ST_Intersects(r.geom, b.geom);
        ALTER TABLE ara_intersect_bati ADD COLUMN id_intersect serial;
        CREATE INDEX IF NOT EXISTS intersect_bati_geom_gist ON ara_intersect_bati USING GIST (geom);
        """ % table_name_bati
        if debug >= 2:
            print(query_intersect)
        executeQuery(connection, query_intersect)

        ##################################################################################################################
        ### Récupération des demi-largeurs de rue et de la hauteur du 1er bâtiment pour chaque segment perpendiculaire ###
        ##################################################################################################################

        print(
            bold + cyan +
            "Récupération des informations nécessaires au calcul du rapport d'aspect :"
            + endC)
        timeLine(
            path_time_log,
            "    Récupération des informations nécessaires au calcul du rapport d'aspect : "
        )

        # Début de la construction de la requête de création des points route, avec infos de demi-largeurs de rue et hauteurs des bâtiments
        query_pt_route = "DROP TABLE IF EXISTS ara_asp_ratio_by_seg;\n"
        query_pt_route += "CREATE TABLE ara_asp_ratio_by_seg (id_seg text, xR float, yR float, width1 float, height1 float, width2 float, height2 float, geom geometry);\n"
        query_pt_route += "INSERT INTO ara_asp_ratio_by_seg VALUES\n"

        # Récupération de la liste des identifiants segments routes (uniquement ceux qui intersectent du bâti)
        cursor.execute(
            "SELECT id_seg FROM ara_intersect_bati GROUP BY id_seg ORDER BY id_seg;"
        )
        id_seg_list = cursor.fetchall()

        # Boucle sur les segments routes
        nb_seg = len(id_seg_list)
        treat_seg = 1
        for id_seg in id_seg_list:
            if debug >= 4:
                print(bold + "    Traitement du segment route : " + endC +
                      str(treat_seg) + "/" + str(nb_seg))

            id_seg = id_seg[0]

            # Table temporaire ne contenant que les intersects d'un segment route donné
            query_temp2_seg = "DROP TABLE IF EXISTS ara_temp2_seg;\n"
            query_temp2_seg += "CREATE TABLE ara_temp2_seg AS SELECT id_seg, id_perp, xR, yR, haut_bati, id_intersect, geom FROM ara_intersect_bati WHERE id_seg = '%s';\n" % (
                id_seg)
            if debug >= 4:
                print(query_temp2_seg)
            executeQuery(connection, query_temp2_seg)

            # Récupération des coordonnées X et Y du point route du segment route associé
            cursor.execute("SELECT xR FROM ara_temp2_seg;")
            xR = cursor.fetchone()
            cursor.execute("SELECT yR FROM ara_temp2_seg;")
            yR = cursor.fetchone()

            # Transformation des coordonnées X et Y du point route du segment route associé en valeurs numériques
            xR = float(str(xR)[1:-2])
            yR = float(str(yR)[1:-2])
            if debug >= 4:
                print("      xR = " + str(xR))
                print("      yR = " + str(yR))
                print("\n")

            # Initialisation des variables demi-largeurs de rue et hauteur du 1er bâtiment intersecté
            w1 = 0
            h1 = 0
            w2 = 0
            h2 = 0

            # Récupération de la liste des identifiants segments perpendiculaires de la table temp2_seg
            cursor.execute(
                "SELECT id_perp FROM ara_temp2_seg GROUP BY id_perp ORDER BY id_perp;"
            )
            id_perp_list = cursor.fetchall()

            # Boucle sur les perpendiculaires (max 2) d'un segment route donné
            for id_perp in id_perp_list:

                # Récupération du numéro de perpendiculaire (1 ou 2 ~ droite ou gauche)
                num_seg = float(str(id_perp)[-4:-3])

                # Initialisation de listes contenant les demi-largeurs de rue et les hauteurs des bâtiments intersectés
                length_list = []
                haut_bati_list = []

                # Table temporaire ne contenant que les intersects d'un segment perpendiculaire donné
                query_temp2_perp = "DROP TABLE IF EXISTS ara_temp2_perp;\n"
                query_temp2_perp += "CREATE TABLE ara_temp2_perp AS SELECT id_seg, id_perp, xR, yR, haut_bati, id_intersect, geom FROM ara_temp2_seg WHERE id_perp = '%s';\n" % (
                    id_perp)
                if debug >= 4:
                    print(query_temp2_perp)
                executeQuery(connection, query_temp2_perp)

                # Récupération de la liste des identifiants segments intersects de la table temp2_perp
                cursor.execute(
                    "SELECT id_intersect FROM ara_temp2_perp GROUP BY id_intersect ORDER BY id_intersect;"
                )
                id_intersect_list = cursor.fetchall()

                # Boucle sur les intersects d'un segment perpendiculaire donné, d'un segment route donné
                for id_intersect in id_intersect_list:

                    # Récupération des coordonnées X et Y des points extrémités de chaque segment intersect
                    query_xI1 = "SELECT ST_X(geom) as X FROM (SELECT ST_AsText(ST_PointN(geom,1)) as geom FROM ara_temp2_perp WHERE id_intersect = '%s') as toto;" % (
                        id_intersect)
                    cursor.execute(query_xI1)
                    xI1 = cursor.fetchone()
                    query_yI1 = "SELECT ST_Y(geom) as Y FROM (SELECT ST_AsText(ST_PointN(geom,1)) as geom FROM ara_temp2_perp WHERE id_intersect = '%s') as toto;" % (
                        id_intersect)
                    cursor.execute(query_yI1)
                    yI1 = cursor.fetchone()
                    query_xI2 = "SELECT ST_X(geom) as X FROM (SELECT ST_AsText(ST_PointN(geom,2)) as geom FROM ara_temp2_perp WHERE id_intersect = '%s') as toto;" % (
                        id_intersect)
                    cursor.execute(query_xI2)
                    xI2 = cursor.fetchone()
                    query_yI2 = "SELECT ST_Y(geom) as Y FROM (SELECT ST_AsText(ST_PointN(geom,2)) as geom FROM ara_temp2_perp WHERE id_intersect = '%s') as toto;" % (
                        id_intersect)
                    cursor.execute(query_yI2)
                    yI2 = cursor.fetchone()

                    # Transformation des coordonnées X et Y des points extrémités de chaque segment intersect en valeurs numériques
                    try:
                        xI1 = float(str(xI1)[1:-2])
                        yI1 = float(str(yI1)[1:-2])
                        xI2 = float(str(xI2)[1:-2])
                        yI2 = float(str(yI2)[1:-2])
                    except ValueError:  # Python renvoie une valeur Null pour les bâtiments en U (= intersectés à plus de 2 points)
                        xI1 = yI1 = xI2 = yI2 = 0
                    if debug >= 4:
                        print("              xI1 = " + str(xI1))
                        print("              yI1 = " + str(yI1))
                        print("              xI2 = " + str(xI2))
                        print("              yI2 = " + str(yI2))

                    # Calcul des distances entre la route et chaque point du segment intersect
                    length_intersect1 = math.sqrt((abs(xR - xI1)**2) +
                                                  (abs(yR - yI1)**2))
                    length_intersect2 = math.sqrt((abs(xR - xI2)**2) +
                                                  (abs(yR - yI2)**2))
                    if debug >= 4:
                        print("              length_intersect1 = " +
                              str(length_intersect1))
                        print("              length_intersect2 = " +
                              str(length_intersect2))

                    # Récupération de la valeur de distance entre la route et le point d'intersect le plus proche (+ ajout dans la liste length_list)
                    length = min(length_intersect1, length_intersect2)
                    length_list.append(length)
                    if debug >= 4:
                        print("              length = " + str(length))

                    # Récupération de la hauteur du bâtiment correspondant à l'intersect (+ ajout dans la liste haut_bati_list)
                    query_haut_bati = "SELECT haut_bati FROM ara_temp2_perp WHERE id_intersect = '%s';" % (
                        id_intersect)
                    cursor.execute(query_haut_bati)
                    haut_bati = cursor.fetchone()
                    haut_bati = float(str(haut_bati)[10:-4])
                    haut_bati_list.append(haut_bati)
                    if debug >= 4:
                        print("              haut_bati = " + str(haut_bati))
                        print("\n")

                # Pour un segment perpendiculaire donné, récupération de la distance minimale entre la route et les intersect avec le bâti
                width = min(length_list)
                if debug >= 4:
                    print("          width = " + str(width))

                # Pour un segment perpendiculaire donné, récupération de la hauteur du bâtiment correspondant au segment intersect le plus proche de la route
                height_position = length_list.index(width)
                height = haut_bati_list[height_position]
                if debug >= 4:
                    print("          height = " + str(height))
                    print("\n")

                # MAJ des variables demi-largeurs de rue et hauteur du 1er bâtiment intersecté suivant le côté de la perpendiculaire par rapport à la route
                if num_seg == 1:
                    w1 = width
                    h1 = height
                elif num_seg == 2:
                    w2 = width
                    h2 = height

            # Construction de la requête de création du point route pour le segment route donné
            query_pt_route += "    ('%s', %s, %s, %s, %s, %s, %s, 'POINT(%s %s)'),\n" % (
                str(id_seg), xR, yR, w1, h1, w2, h2, xR, yR)

            treat_seg += 1

        # Fin de la construction de la requête de création des points route, avec infos de demi-largeurs de rue et hauteurs des bâtiments
        query_pt_route = query_pt_route[:-2] + ";\n"  # Transformer la virgule de la dernière ligne SQL en point-virgule (pour terminer la requête)
        query_pt_route += "ALTER TABLE ara_asp_ratio_by_seg ALTER COLUMN geom TYPE geometry(POINT,%s) USING ST_SetSRID(geom,%s);\n" % (
            epsg, epsg)  # Mise à jour du système de coordonnées
        query_pt_route += "CREATE INDEX IF NOT EXISTS asp_ratio_by_seg_geom_gist ON ara_asp_ratio_by_seg USING GIST (geom);\n"
        if debug >= 2:
            print(query_pt_route)
        executeQuery(connection, query_pt_route)

        ###########################################################
        ### Calcul de l'indicateur et export de la table finale ###
        ###########################################################

        print(bold + cyan +
              "Calculs finaux de l'indicateur de rapport d'aspect :" + endC)
        timeLine(path_time_log,
                 "    Calculs finaux de l'indicateur de rapport d'aspect : ")

        # Requête de calcul d'un rapport d'aspect par segment route
        query_asp_ratio_by_seg = """
        ALTER TABLE ara_asp_ratio_by_seg ADD COLUMN asp_ratio float;
        UPDATE ara_asp_ratio_by_seg SET asp_ratio = 0;
        UPDATE ara_asp_ratio_by_seg SET asp_ratio = ((height1 + height2) / 2) / (width1 + width2) WHERE height1 <> 0 AND height2 <> 0 AND width1 <> 0 AND width2 <> 0;
        """
        if debug >= 2:
            print(query_asp_ratio_by_seg)
        executeQuery(connection, query_asp_ratio_by_seg)

        # Requête de bufferisation du fichier maillage
        query_buffer = """
        DROP TABLE IF EXISTS ara_buffer;
        CREATE TABLE ara_buffer AS
            SELECT ID as ID, ST_Buffer(geom, %s) as geom
            FROM %s;
        CREATE INDEX IF NOT EXISTS buffer_geom_gist ON ara_buffer USING GIST (geom);
        """ % (buffer_size, table_name_maille)
        if debug >= 2:
            print(query_buffer)
        executeQuery(connection, query_buffer)

        # Requête de calcul d'un rapport d'aspect par maille (via un intersect sur le maillage bufferisé)
        query_asp_ratio_temp1 = """
        DROP TABLE IF EXISTS ara_asp_ratio_temp1;
        CREATE TABLE ara_asp_ratio_temp1 AS
            SELECT m.ID as ID, avg(r.asp_ratio) as asp_ratio, m.geom as geom
            FROM %s as m, ara_buffer as b, ara_asp_ratio_by_seg as r
            WHERE ST_Intersects(b.geom, r.geom)
                AND m.ID = b.ID
                AND r.asp_ratio > 0
            GROUP BY m.ID, m.geom;
        CREATE INDEX IF NOT EXISTS asp_ratio_temp1_geom_gist ON ara_asp_ratio_temp1 USING GIST (geom);
        """ % (table_name_maille)
        if debug >= 2:
            print(query_asp_ratio_temp1)
        executeQuery(connection, query_asp_ratio_temp1)

        # Rapport d'aspect pour les mailles n'intersectant pas de points-route avec un rapport d'aspect
        query_asp_ratio_temp2 = """
        DROP TABLE IF EXISTS ara_asp_ratio_temp2;
        CREATE TABLE ara_asp_ratio_temp2 AS
            SELECT DISTINCT ID as ID, geom as geom
            FROM %s
            WHERE ID NOT IN
                (SELECT DISTINCT ID
                FROM ara_asp_ratio_temp1);
        ALTER TABLE ara_asp_ratio_temp2 ADD COLUMN asp_ratio float;
        UPDATE ara_asp_ratio_temp2 SET asp_ratio = 0;
        CREATE INDEX IF NOT EXISTS asp_ratio_temp2_geom_gist ON ara_asp_ratio_temp2 USING GIST (geom);
        """ % table_name_maille
        if debug >= 1:
            print(query_asp_ratio_temp2)
        executeQuery(connection, query_asp_ratio_temp2)

        # Fusion des 2 tables précédentes pour retrouver l'ensemble des mailles de départ
        query_asp_ratio = """
        DROP TABLE IF EXISTS ara_asp_ratio;
        CREATE TABLE ara_asp_ratio AS
            SELECT ID, asp_ratio, geom
            FROM ara_asp_ratio_temp1
            UNION
            SELECT ID, asp_ratio, geom
            FROM ara_asp_ratio_temp2;
        ALTER TABLE ara_asp_ratio ALTER COLUMN ID TYPE INTEGER;
        """
        if debug >= 2:
            print(query_asp_ratio)
        executeQuery(connection, query_asp_ratio)
        closeConnection(connection)
        exportVectorByOgr2ogr(database_postgis,
                              grid_output,
                              'ara_asp_ratio',
                              user_name=user_postgis,
                              password=password_postgis,
                              ip_host=server_postgis,
                              num_port=str(port_number),
                              schema_name=schema_postgis,
                              format_type=format_vector)

        ##########################################
        ### Nettoyage des fichiers temporaires ###
        ##########################################

        if not save_results_intermediate:
            if os.path.exists(temp_path):
                shutil.rmtree(temp_path)
            # ~ dropDatabase(database_postgis) # Conflits avec autres indicateurs (Height of Roughness Elements / Terrain Roughness Class)

    else:
        print(bold + magenta + "Le calcul de Aspect Ratio a déjà eu lieu." +
              endC)

    print(bold + yellow + "Fin du calcul de l'indicateur Aspect Ratio." +
          endC + "\n")
    timeLine(path_time_log, "Fin du calcul de l'indicateur Aspect Ratio : ")

    return
Пример #2
0
def statisticsVectorRaster(image_input,
                           vector_input,
                           vector_output,
                           band_number,
                           enable_stats_all_count,
                           enable_stats_columns_str,
                           enable_stats_columns_real,
                           col_to_delete_list,
                           col_to_add_list,
                           class_label_dico,
                           path_time_log,
                           clean_small_polygons=False,
                           format_vector='ESRI Shapefile',
                           save_results_intermediate=False,
                           overwrite=True):

    # INITIALISATION
    if debug >= 3:
        print(cyan + "statisticsVectorRaster() : " + endC + "image_input : " +
              str(image_input) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC + "vector_input : " +
              str(vector_input) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "vector_output : " + str(vector_output) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC + "band_number : " +
              str(band_number) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "enable_stats_all_count : " + str(enable_stats_all_count) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "enable_stats_columns_str : " + str(enable_stats_columns_str) +
              endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "enable_stats_columns_real : " + str(enable_stats_columns_real) +
              endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "col_to_delete_list : " + str(col_to_delete_list) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "col_to_add_list : " + str(col_to_add_list) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "class_label_dico : " + str(class_label_dico) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "clean_small_polygons : " + str(clean_small_polygons) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "path_time_log : " + str(path_time_log) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "format_vector : " + str(format_vector) + endC)
        print(cyan + "statisticsVectorRaster() : " + endC +
              "save_results_intermediate : " + str(save_results_intermediate) +
              endC)
        print(cyan + "statisticsVectorRaster() : " + endC + "overwrite : " +
              str(overwrite) + endC)

    # Constantes
    PREFIX_AREA_COLUMN = "S_"

    # Mise à jour du Log
    starting_event = "statisticsVectorRaster() : Compute statistic crossing starting : "
    timeLine(path_time_log, starting_event)

    # creation du fichier vecteur de sortie
    if vector_output == "":
        vector_output = vector_input  # Précisé uniquement pour l'affichage
    else:
        # Copy vector_output
        copyVectorFile(vector_input, vector_output, format_vector)

    # Vérifications
    image_xmin, image_xmax, image_ymin, image_ymax = getEmpriseImage(
        image_input)
    vector_xmin, vector_xmax, vector_ymin, vector_ymax = getEmpriseFile(
        vector_output, format_vector)
    extension_vector = os.path.splitext(vector_output)[1]

    if round(vector_xmin, 4) < round(image_xmin, 4) or round(
            vector_xmax, 4) > round(image_xmax, 4) or round(
                vector_ymin, 4) < round(image_ymin, 4) or round(
                    vector_ymax, 4) > round(image_ymax, 4):
        print(cyan + "statisticsVectorRaster() : " + bold + red +
              "image_xmin, image_xmax, image_ymin, image_ymax" + endC,
              image_xmin,
              image_xmax,
              image_ymin,
              image_ymax,
              file=sys.stderr)
        print(cyan + "statisticsVectorRaster() : " + bold + red +
              "vector_xmin, vector_xmax, vector_ymin, vector_ymax" + endC,
              vector_xmin,
              vector_xmax,
              vector_ymin,
              vector_ymax,
              file=sys.stderr)
        raise NameError(
            cyan + "statisticsVectorRaster() : " + bold + red +
            "The extend of the vector file (%s) is greater than the image file (%s)"
            % (vector_output, image_input) + endC)

    pixel_size = getPixelSizeImage(image_input)

    # Suppression des très petits polygones qui introduisent des valeurs NaN
    if clean_small_polygons:
        min_size_area = pixel_size * 2
        vector_temp = os.path.splitext(
            vector_output)[0] + "_temp" + extension_vector

        cleanMiniAreaPolygons(vector_output, vector_temp, min_size_area, '',
                              format_vector)
        removeVectorFile(vector_output, format_vector)
        renameVectorFile(vector_temp, vector_output)

    # Récuperation du driver pour le format shape
    driver = ogr.GetDriverByName(format_vector)

    # Ouverture du fichier shape en lecture-écriture
    data_source = driver.Open(vector_output,
                              1)  # 0 means read-only - 1 means writeable.
    if data_source is None:
        print(cyan + "statisticsVectorRaster() : " + bold + red +
              "Impossible d'ouvrir le fichier shape : " + vector_output + endC,
              file=sys.stderr)
        sys.exit(1)  # exit with an error code

    # Récupération du vecteur
    layer = data_source.GetLayer(
        0)  # Recuperation de la couche (une couche contient les polygones)
    layer_definition = layer.GetLayerDefn(
    )  # GetLayerDefn => returns the field names of the user defined (created) fields

    # ETAPE 1/4 : CREATION AUTOMATIQUE DU DICO DE VALEUR SI IL N'EXISTE PAS
    if enable_stats_all_count and class_label_dico == {}:
        image_values_list = identifyPixelValues(image_input)
        # Pour toutes les valeurs
        for id_value in image_values_list:
            class_label_dico[id_value] = str(id_value)
        # Suppression de la valeur no date à 0
        if 0 in class_label_dico:
            del class_label_dico[0]
    if debug >= 2:
        print(class_label_dico)

    # ETAPE 2/4 : CREATION DES COLONNES DANS LE FICHIER SHAPE
    if debug >= 2:
        print(
            cyan + "statisticsVectorRaster() : " + bold + green +
            "ETAPE 1/3 : DEBUT DE LA CREATION DES COLONNES DANS LE FICHIER VECTEUR %s"
            % (vector_output) + endC)

    # En entrée :
    # col_to_add_list = [UniqueID, majority/DateMaj/SrcMaj, minority, min, max, mean, median, sum, std, unique, range, all, count, all_S, count_S] - all traduisant le class_label_dico en autant de colonnes
    # Sous_listes de col_to_add_list à identifier pour des facilités de manipulations ultérieures:
    # col_to_add_inter01_list = [majority/DateMaj/SrcMaj, minority, min, max, mean, median, sum, std, unique, range]
    # col_to_add_inter02_list = [majority, minority, min, max, mean, median, sum, std, unique, range, all, count, all_S, count_S]
    # Construction des listes intermédiaires
    col_to_add_inter01_list = []

    # Valeurs à injecter dans des colonnes - Format String
    if enable_stats_columns_str:
        stats_columns_str_list = ['majority', 'minority']
        for e in stats_columns_str_list:
            col_to_add_list.append(e)

    # Valeurs à injecter dans des colonnes - Format Nbr
    if enable_stats_columns_real:
        stats_columns_real_list = [
            'min', 'max', 'mean', 'median', 'sum', 'std', 'unique', 'range'
        ]
        for e in stats_columns_real_list:
            col_to_add_list.append(e)

    # Valeurs à injecter dans des colonnes - Format Nbr
    if enable_stats_all_count:
        stats_all_count_list = ['all', 'count']
        for e in stats_all_count_list:
            col_to_add_list.append(e)

    # Valeurs à injecter dans des colonnes - si class_label_dico est non vide
    if class_label_dico != {}:
        stats_all_count_list = ['all', 'count']
        for e in stats_all_count_list:
            if not e in col_to_add_list:
                col_to_add_list.append(e)

    # Ajout colonne par colonne
    if "majority" in col_to_add_list:
        col_to_add_inter01_list.append("majority")
    if "DateMaj" in col_to_add_list:
        col_to_add_inter01_list.append("DateMaj")
    if "SrcMaj" in col_to_add_list:
        col_to_add_inter01_list.append("SrcMaj")
    if "minority" in col_to_add_list:
        col_to_add_inter01_list.append("minority")
    if "min" in col_to_add_list:
        col_to_add_inter01_list.append("min")
    if "max" in col_to_add_list:
        col_to_add_inter01_list.append("max")
    if "mean" in col_to_add_list:
        col_to_add_inter01_list.append("mean")
    if "median" in col_to_add_list:
        col_to_add_inter01_list.append("median")
    if "sum" in col_to_add_list:
        col_to_add_inter01_list.append("sum")
    if "std" in col_to_add_list:
        col_to_add_inter01_list.append("std")
    if "unique" in col_to_add_list:
        col_to_add_inter01_list.append("unique")
    if "range" in col_to_add_list:
        col_to_add_inter01_list.append("range")

    # Copy de col_to_add_inter01_list dans col_to_add_inter02_list
    col_to_add_inter02_list = list(col_to_add_inter01_list)

    if "all" in col_to_add_list:
        col_to_add_inter02_list.append("all")
    if "count" in col_to_add_list:
        col_to_add_inter02_list.append("count")
    if "all_S" in col_to_add_list:
        col_to_add_inter02_list.append("all_S")
    if "count_S" in col_to_add_list:
        col_to_add_inter02_list.append("count_S")
    if "DateMaj" in col_to_add_inter02_list:
        col_to_add_inter02_list.remove("DateMaj")
        col_to_add_inter02_list.insert(0, "majority")
    if "SrcMaj" in col_to_add_inter02_list:
        col_to_add_inter02_list.remove("SrcMaj")
        col_to_add_inter02_list.insert(0, "majority")

    # Valeurs à injecter dans des colonnes - Format Nbr
    if enable_stats_all_count:
        stats_all_count_list = ['all_S', 'count_S']
        for e in stats_all_count_list:
            col_to_add_list.append(e)

    # Creation de la colonne de l'identifiant unique
    if ("UniqueID" in col_to_add_list) or ("uniqueID" in col_to_add_list) or (
            "ID" in col_to_add_list):
        field_defn = ogr.FieldDefn(
            "ID", ogr.OFTInteger
        )  # Création du nom du champ dans l'objet stat_classif_field_defn
        layer.CreateField(field_defn)
        if debug >= 3:
            print(cyan + "statisticsVectorRaster() : " + endC +
                  "Creation de la colonne : ID")

    # Creation des colonnes de col_to_add_inter01_list ([majority/DateMaj/SrcMaj, minority, min, max, mean, median, sum, std, unique, range])
    for col in col_to_add_list:
        if layer_definition.GetFieldIndex(
                col
        ) == -1:  # Vérification de l'existence de la colonne col (retour = -1 : elle n'existe pas)
            if col == 'majority' or col == 'DateMaj' or col == 'SrcMaj' or col == 'minority':  # Identification de toutes les colonnes remplies en string
                stat_classif_field_defn = ogr.FieldDefn(
                    col, ogr.OFTString
                )  # Création du champ (string) dans l'objet stat_classif_field_defn
                layer.CreateField(stat_classif_field_defn)
            elif col == 'mean' or col == 'median' or col == 'sum' or col == 'std' or col == 'unique' or col == 'range' or col == 'max' or col == 'min':
                stat_classif_field_defn = ogr.FieldDefn(
                    col, ogr.OFTReal
                )  # Création du champ (real) dans l'objet stat_classif_field_defn
                # Définition de la largeur du champ
                stat_classif_field_defn.SetWidth(20)
                # Définition de la précision du champ valeur flottante
                stat_classif_field_defn.SetPrecision(2)
                layer.CreateField(stat_classif_field_defn)
            if debug >= 3:
                print(cyan + "statisticsVectorRaster() : " + endC +
                      "Creation de la colonne : " + str(col))

    # Creation des colonnes reliées au dictionnaire
    if ('all' in col_to_add_list) or ('count' in col_to_add_list) or (
            'all_S' in col_to_add_list) or ('count_S' in col_to_add_list):
        for col in class_label_dico:

            # Gestion du nom de la colonne correspondant à la classe
            name_col = class_label_dico[col]
            if len(name_col) > 10:
                name_col = name_col[:10]
                print(
                    cyan + "statisticsVectorRaster() : " + bold + yellow +
                    "Nom de la colonne trop long. Il sera tronque a 10 caracteres en cas d'utilisation: "
                    + endC + name_col)

            # Gestion du nom de la colonne correspondant à la surface de la classe
            name_col_area = PREFIX_AREA_COLUMN + name_col
            if len(name_col_area) > 10:
                name_col_area = name_col_area[:10]
                if debug >= 3:
                    print(
                        cyan + "statisticsVectorRaster() : " + bold + yellow +
                        "Nom de la colonne trop long. Il sera tronque a 10 caracteres en cas d'utilisation: "
                        + endC + name_col_area)

            # Ajout des colonnes de % de répartition des éléments du raster
            if ('all' in col_to_add_list) or ('count' in col_to_add_list):
                if layer_definition.GetFieldIndex(
                        name_col
                ) == -1:  # Vérification de l'existence de la colonne name_col (retour = -1 : elle n'existe pas)
                    stat_classif_field_defn = ogr.FieldDefn(
                        name_col, ogr.OFTReal
                    )  # Création du champ (real) dans l'objet stat_classif_field_defn
                    # Définition de la largeur du champ
                    stat_classif_field_defn.SetWidth(20)
                    # Définition de la précision du champ valeur flottante
                    stat_classif_field_defn.SetPrecision(2)
                    if debug >= 3:
                        print(cyan + "statisticsVectorRaster() : " + endC +
                              "Creation de la colonne : " + str(name_col))
                    layer.CreateField(
                        stat_classif_field_defn)  # Ajout du champ

            # Ajout des colonnes de surface des éléments du raster
            if ('all_S' in col_to_add_list) or ('count_S' in col_to_add_list):
                if layer_definition.GetFieldIndex(
                        name_col_area
                ) == -1:  # Vérification de l'existence de la colonne name_col_area (retour = -1 : elle n'existe pas)
                    stat_classif_field_defn = ogr.FieldDefn(
                        name_col_area, ogr.OFTReal
                    )  # Création du nom du champ dans l'objet stat_classif_field_defn
                    # Définition de la largeur du champ
                    stat_classif_field_defn.SetWidth(20)
                    # Définition de la précision du champ valeur flottante
                    stat_classif_field_defn.SetPrecision(2)

                    if debug >= 3:
                        print(cyan + "statisticsVectorRaster() : " + endC +
                              "Creation de la colonne : " + str(name_col_area))
                    layer.CreateField(
                        stat_classif_field_defn)  # Ajout du champ

    if debug >= 2:
        print(
            cyan + "statisticsVectorRaster() : " + bold + green +
            "ETAPE 1/3 : FIN DE LA CREATION DES COLONNES DANS LE FICHIER VECTEUR %s"
            % (vector_output) + endC)

    # ETAPE 3/4 : REMPLISSAGE DES COLONNES DU VECTEUR
    if debug >= 2:
        print(cyan + "statisticsVectorRaster() : " + bold + green +
              "ETAPE 2/3 : DEBUT DU REMPLISSAGE DES COLONNES DU VECTEUR " +
              endC)

    # Calcul des statistiques col_to_add_inter02_list = [majority, minority, min, max, mean, median, sum, std, unique, range, all, count, all_S, count_S] de croisement images_raster / vecteur
    # Utilisation de la librairie rasterstat
    if debug >= 3:
        print(cyan + "statisticsVectorRaster() : " + bold + green +
              "Calcul des statistiques " + endC +
              "Stats : %s - Vecteur : %s - Raster : %s" %
              (col_to_add_inter02_list, vector_output, image_input) + endC)
    stats_info_list = raster_stats(vector_output,
                                   image_input,
                                   band_num=band_number,
                                   stats=col_to_add_inter02_list)

    # Decompte du nombre de polygones
    num_features = layer.GetFeatureCount()
    if debug >= 3:
        print(cyan + "statisticsVectorRaster() : " + bold + green +
              "Remplissage des colonnes polygone par polygone " + endC)
    if debug >= 3:
        print(cyan + "statisticsVectorRaster() : " + endC +
              "Nombre total de polygones : " + str(num_features))

    polygone_count = 0

    for polygone_stats in stats_info_list:  # Pour chaque polygone représenté dans stats_info_list - et il y a autant de polygone que dans le fichier vecteur

        # Extraction de feature
        feature = layer.GetFeature(polygone_stats['__fid__'])

        polygone_count = polygone_count + 1

        if debug >= 3 and polygone_count % 10000 == 0:
            print(cyan + "statisticsVectorRaster() : " + endC +
                  "Avancement : %s polygones traites sur %s" %
                  (polygone_count, num_features))
        if debug >= 5:
            print(
                cyan + "statisticsVectorRaster() : " + endC +
                "Traitement du polygone : ",
                stats_info_list.index(polygone_stats) + 1)

        # Remplissage de l'identifiant unique
        if ("UniqueID" in col_to_add_list) or (
                "uniqueID" in col_to_add_list) or ("ID" in col_to_add_list):
            feature.SetField('ID', int(stats_info_list.index(polygone_stats)))

        # Initialisation à 0 des colonnes contenant le % de répartition de la classe - Verifier ce qu'il se passe si le nom dépasse 10 caracteres
        if ('all' in col_to_add_list) or ('count' in col_to_add_list):
            for element in class_label_dico:
                name_col = class_label_dico[element]
                if len(name_col) > 10:
                    name_col = name_col[:10]
                feature.SetField(name_col, 0)

        # Initialisation à 0 des colonnes contenant la surface correspondant à la classe - Verifier ce qu'il se passe si le nom dépasse 10 caracteres
        if ('all_S' in col_to_add_list) or ('count_S' in col_to_add_list):
            for element in class_label_dico:
                name_col = class_label_dico[element]
                name_col_area = PREFIX_AREA_COLUMN + name_col
                if len(name_col_area) > 10:
                    name_col_area = name_col_area[:10]
                feature.SetField(name_col_area, 0)

        # Remplissage des colonnes contenant le % de répartition et la surface des classes
        if ('all' in col_to_add_list) or ('count' in col_to_add_list) or (
                'all_S' in col_to_add_list) or ('count_S' in col_to_add_list):
            # 'all' est une liste des couples : (Valeur_du_pixel_sur_le_raster, Nbr_pixel_ayant_cette_valeur) pour le polygone observe.
            # Ex : [(0,183),(803,45),(801,4)] : dans le polygone, il y a 183 pixels de valeur 0, 45 pixels de valeur 803 et 4 pixels de valeur 801
            majority_all = polygone_stats['all']

            # Deux valeurs de pixel peuvent faire référence à une même colonne. Par exemple : les pixels à 201, 202, 203 peuvent correspondre à la BD Topo
            # Regroupement des éléments de majority_all allant dans la même colonne au regard de class_label_dico
            count_for_idx_couple = 0  # Comptage du nombre de modifications (suppression de couple) de majority_all pour adapter la valeur de l'index lors de son parcours

            for idx_couple in range(
                    1, len(majority_all)
            ):  # Inutile d'appliquer le traitement au premier élément (idx_couple == 0)

                idx_couple = idx_couple - count_for_idx_couple  # Prise en compte dans le parcours de majority_all des couples supprimés
                couple = majority_all[idx_couple]  # Ex : couple = (803,45)

                if (couple is None) or (
                        couple == ""
                ):  # en cas de bug de rasterstats (erreur geometrique du polygone par exemple)
                    if debug >= 3:
                        print(
                            cyan + "statisticsVectorRaster() : " + bold + red +
                            "Probleme detecte dans la gestion du polygone %s" %
                            (polygone_count) + endC,
                            file=sys.stderr)
                    pass
                else:
                    for idx_verif in range(idx_couple):
                        # Vérification au regard des éléments présents en amont dans majority_all
                        # Cas où le nom correspondant au label a déjà été rencontré dans majority_all
                        # Vérification que les pixels de l'image sont réferncés dans le dico
                        if couple[0] in class_label_dico:

                            if class_label_dico[couple[0]] == class_label_dico[
                                    majority_all[idx_verif][0]]:
                                majority_all[idx_verif] = (
                                    majority_all[idx_verif][0],
                                    majority_all[idx_verif][1] + couple[1]
                                )  # Ajout du nombre de pixels correspondant dans le couple précédent
                                majority_all.remove(
                                    couple
                                )  # Supression du couple présentant le "doublon"
                                count_for_idx_couple = count_for_idx_couple + 1  # Mise à jour du décompte de modifications
                                break
                        else:
                            raise NameError(
                                cyan + "statisticsVectorRaster() : " + bold +
                                red +
                                "The image file (%s) contain pixel value '%d' not identified into class_label_dico"
                                % (image_input, couple[0]) + endC)

            # Intégration des valeurs de majority all dans les colonnes
            for couple_value_count in majority_all:  # Parcours de majority_all. Ex : couple_value_count = (803,45)
                if (couple_value_count is None) or (
                        couple_value_count == ""
                ):  # en cas de bug de rasterstats (erreur geometrique du polygone par exemple)
                    if debug >= 3:
                        print(
                            cyan + "statisticsVectorRaster() : " + bold + red +
                            "Probleme detecte dans la gestion du polygone %s" %
                            (polygone_count) + endC,
                            file=sys.stderr)
                    pass
                else:
                    nb_pixel_total = polygone_stats[
                        'count']  # Nbr de pixels du polygone
                    pixel_value = couple_value_count[0]  # Valeur du pixel
                    value_count = couple_value_count[
                        1]  # Nbr de pixels ayant cette valeur
                    name_col = class_label_dico[
                        pixel_value]  # Transformation de la valeur du pixel en "signification" au regard du dictionnaire. Ex : BD Topo ou 2011
                    name_col_area = PREFIX_AREA_COLUMN + name_col  # Identification du nom de la colonne en surfaces

                    if len(name_col) > 10:
                        name_col = name_col[:10]
                    if len(name_col_area) > 10:
                        name_col_area = name_col_area[:10]

                    value_area = pixel_size * value_count  # Calcul de la surface du polygone correspondant à la valeur du pixel
                    if nb_pixel_total != None and nb_pixel_total != 0:
                        percentage = (
                            float(value_count) / float(nb_pixel_total)
                        ) * 100  # Conversion de la surface en pourcentages, arondi au pourcent
                    else:
                        if debug >= 3:
                            print(
                                cyan + "statisticsVectorRaster() : " + bold +
                                red +
                                "Probleme dans l'identification du nombre de pixels du polygone %s : le pourcentage de %s est mis à 0"
                                % (polygone_count, name_col) + endC,
                                file=sys.stderr)
                        percentage = 0.0

                    if ('all' in col_to_add_list) or ('count'
                                                      in col_to_add_list):
                        feature.SetField(
                            name_col, percentage
                        )  # Injection du pourcentage dans la colonne correpondante
                    if ('all_S' in col_to_add_list) or ('count_S'
                                                        in col_to_add_list):
                        feature.SetField(
                            name_col_area, value_area
                        )  # Injection de la surface dans la colonne correpondante
        else:
            pass

        # Remplissage des colonnes statistiques demandées ( col_to_add_inter01_list = [majority/DateMaj/SrcMaj, minority, min, max, mean, median, sum, std, unique, range] )
        for stats in col_to_add_inter01_list:

            if stats == 'DateMaj' or stats == 'SrcMaj':  # Cas particulier de 'DateMaj' et 'SrcMaj' : le nom de la colonne est DateMaj ou SrcMaj, mais la statistique utilisée est identifiée par majority
                name_col = stats  # Nom de la colonne. Ex : 'DateMaj'
                value_statis = polygone_stats[
                    'majority']  # Valeur majoritaire. Ex : '203'
                if value_statis == None:
                    value_statis_class = 'nan'
                else:
                    value_statis_class = class_label_dico[
                        value_statis]  # Transformation de la valeur au regard du dictionnaire. Ex : '2011'
                feature.SetField(name_col,
                                 value_statis_class)  # Ajout dans la colonne

            elif (stats is None) or (stats == "") or (
                    polygone_stats[stats] is
                    None) or (polygone_stats[stats]) == "" or (
                        polygone_stats[stats]) == 'nan':
                # En cas de bug de rasterstats (erreur geometrique du polygone par exemple)
                pass

            else:
                name_col = stats  # Nom de la colonne. Ex : 'majority', 'max'
                value_statis = polygone_stats[
                    stats]  # Valeur à associer à la colonne, par exemple '2011'

                if (
                        name_col == 'majority' or name_col == 'minority'
                ) and class_label_dico != []:  # Cas où la colonne fait référence à une valeur du dictionnaire
                    value_statis_class = class_label_dico[value_statis]
                else:
                    value_statis_class = value_statis

                feature.SetField(name_col, value_statis_class)

        layer.SetFeature(feature)
        feature.Destroy()

    if debug >= 2:
        print(cyan + "statisticsVectorRaster() : " + bold + green +
              "ETAPE 2/3 : FIN DU REMPLISSAGE DES COLONNES DU VECTEUR %s" %
              (vector_output) + endC)

    # ETAPE 4/4 : SUPRESSION DES COLONNES NON SOUHAITEES
    if col_to_delete_list != []:

        if debug >= 2:
            print(cyan + "statisticsVectorRaster() : " + bold + green +
                  "ETAPE 3/3 : DEBUT DES SUPPRESSIONS DES COLONNES %s" %
                  (col_to_delete_list) + endC)

        for col_to_delete in col_to_delete_list:

            if layer_definition.GetFieldIndex(
                    col_to_delete
            ) != -1:  # Vérification de l'existence de la colonne col (retour = -1 : elle n'existe pas)

                layer.DeleteField(layer_definition.GetFieldIndex(
                    col_to_delete))  # Suppression de la colonne

                if debug >= 3:
                    print(cyan + "statisticsVectorRaster() : " + endC +
                          "Suppression de %s" % (col_to_delete) + endC)

        if debug >= 2:
            print(cyan + "statisticsVectorRaster() : " + bold + green +
                  "ETAPE 3/3 : FIN DE LA SUPPRESSION DES COLONNES" + endC)

    else:
        print(cyan + "statisticsVectorRaster() : " + bold + yellow +
              "ETAPE 3/3 : AUCUNE SUPPRESSION DE COLONNE DEMANDEE" + endC)

    # Fermeture du fichier shape
    layer.SyncToDisk()
    layer = None
    data_source.Destroy()

    # Mise à jour du Log
    ending_event = "statisticsVectorRaster() : Compute statistic crossing ending : "
    timeLine(path_time_log, ending_event)

    return
Пример #3
0
def vectorsListToOcs(input_text,
                     output_raster,
                     footprint_vector,
                     reference_raster,
                     codage_raster='uint8',
                     epsg=2154,
                     no_data_value=0,
                     format_raster='GTiff',
                     format_vector='ESRI Shapefile',
                     extension_raster='.tif',
                     extension_vector='.shp',
                     path_time_log='',
                     save_results_intermediate=False,
                     overwrite=True):

    if debug >= 3:
        print(
            '\n' + bold + green +
            "OCS raster à partir d'une liste de vecteurs - Variables dans la fonction :"
            + endC)
        print(cyan + "    vectorsListToOcs() : " + endC + "input_text : " +
              str(input_text) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC + "output_raster : " +
              str(output_raster) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC +
              "footprint_vector : " + str(footprint_vector) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC +
              "reference_raster : " + str(reference_raster) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC + "codage_raster : " +
              str(codage_raster) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC + "epsg : " +
              str(epsg) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC + "no_data_value : " +
              str(no_data_value) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC + "format_raster : " +
              str(format_raster) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC + "format_vector : " +
              str(format_vector) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC +
              "extension_raster : " + str(extension_raster) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC +
              "extension_vector : " + str(extension_vector) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC + "path_time_log : " +
              str(path_time_log) + endC)
        print(cyan + "    vectorsListToOcs() : " + endC +
              "save_results_intermediate : " + str(save_results_intermediate) +
              endC)
        print(cyan + "    vectorsListToOcs() : " + endC + "overwrite : " +
              str(overwrite) + endC + '\n')

    # Définition des constantes
    SUFFIX_TEMP = '_temp'
    SUFFIX_CUT = '_cut'
    SUFFIX_FILTER = '_filter'
    SUFFIX_BUFFER = '_buffer'
    TEXT_SEPARATOR = ':'

    # Mise à jour du log
    starting_event = "vectorsListToOcs() : Début du traitement : "
    timeLine(path_time_log, starting_event)

    print(cyan + "vectorsListToOcs() : " + bold + green +
          "DEBUT DES TRAITEMENTS" + endC + '\n')

    # Définition des variables 'basename'
    output_raster_basename = os.path.basename(
        os.path.splitext(output_raster)[0])
    output_raster_dirname = os.path.dirname(output_raster)

    # Définition des variables temp
    temp_directory = output_raster_dirname + os.sep + output_raster_basename + SUFFIX_TEMP
    temp_raster = temp_directory + os.sep + output_raster_basename + SUFFIX_TEMP + extension_raster

    # Nettoyage des traitements précédents
    if overwrite:
        if debug >= 3:
            print(cyan + "vectorsListToOcs() : " + endC +
                  "Nettoyage des traitements précédents." + '\n')
        removeFile(output_raster)
        cleanTempData(temp_directory)
    else:
        if os.path.exists(output_raster):
            print(cyan + "vectorsListToOcs() : " + bold + yellow +
                  "Le fichier de sortie existe déjà et ne sera pas regénéré." +
                  endC)
            raise
        if not os.path.exixts(temp_directory):
            os.makedirs(temp_directory)
        pass

    # Test de l'emprise des fichiers vecteur d'emprise et raster de référence (le raster doit être de même taille ou plus grand que le vecteur)
    xmin_fpt, xmax_fpt, ymin_fpt, ymax_fpt = getEmpriseFile(
        footprint_vector, format_vector=format_vector)
    xmin_ref, xmax_ref, ymin_ref, ymax_ref = getEmpriseImage(reference_raster)
    if round(xmin_fpt, 4) < round(xmin_ref, 4) or round(xmax_fpt, 4) > round(
            xmax_ref, 4) or round(ymin_fpt, 4) < round(ymin_ref, 4) or round(
                ymax_fpt, 4) > round(ymax_ref, 4):
        print(cyan + "vectorsListToOcs() : " + bold + red +
              "xmin_fpt, xmax_fpt, ymin_fpt, ymax_fpt" + endC,
              xmin_fpt,
              xmax_fpt,
              ymin_fpt,
              ymax_fpt,
              file=sys.stderr)
        print(cyan + "vectorsListToOcs() : " + bold + red +
              "xmin_ref, xmax_ref, ymin_ref, ymax_ref" + endC,
              xmin_ref,
              xmax_ref,
              ymin_ref,
              ymax_ref,
              file=sys.stderr)
        raise NameError(
            cyan + "vectorsListToOcs() : " + bold + red +
            "The extend of the footprint vector (%s) is greater than the reference raster (%s)."
            % (footprint_vector, reference_raster) + endC)

    # Récupération des traitements à faire dans le fichier texte d'entrée
    text_list = readTextFileBySeparator(input_text, TEXT_SEPARATOR)

    ####################################################################

    print(cyan + "vectorsListToOcs() : " + bold + green +
          "Début de la génération de l'OCS raster à partir de vecteurs." +
          endC + '\n')

    # Boucle sur les traitements à réaliser
    for text in text_list:
        idx = text_list.index(text) + 1
        class_label = int(text[0])
        vector_file = text[1]
        if debug >= 3:
            print(cyan + "vectorsListToOcs() : " + endC + bold +
                  "Génération %s/%s : " % (idx, len(text_list)) + endC +
                  "traitement du fichier %s (label %s)." %
                  (vector_file, str(class_label)) + '\n')

        # Gestion des noms des fichiers temporaires
        vector_file_basename = os.path.basename(
            os.path.splitext(vector_file)[0])
        vector_file_cut = temp_directory + os.sep + vector_file_basename + SUFFIX_CUT + extension_vector
        vector_file_filter = temp_directory + os.sep + vector_file_basename + SUFFIX_FILTER + extension_vector
        vector_file_buffer = temp_directory + os.sep + vector_file_basename + SUFFIX_BUFFER + extension_vector
        vector_file_raster = temp_directory + os.sep + vector_file_basename + extension_raster

        # Gestion des variables de traitement (tampon et filtrage SQL)
        try:
            buffer_len = float(text[2])
        except ValueError:
            buffer_len = text[2]
        except Exception:
            buffer_len = ''
        try:
            sql_filter = text[3]
        except Exception:
            sql_filter = ''

        # Découpage à l'emprise de la zone d'étude
        if debug >= 3:
            print(cyan + "vectorsListToOcs() : " + endC +
                  "Découpage à l'emprise de la zone d'étude." + '\n')
        cutVectorAll(footprint_vector,
                     vector_file,
                     vector_file_cut,
                     overwrite=overwrite,
                     format_vector=format_vector)

        # Filtrage SQL (facultatif)
        if sql_filter != '':
            if debug >= 3:
                print(cyan + "vectorsListToOcs() : " + endC +
                      "Application du filtrage SQL : %s." % sql_filter + '\n')
            attr_names_list = getAttributeNameList(vector_file_cut,
                                                   format_vector=format_vector)
            column = "'"
            for attr_name in attr_names_list:
                column += attr_name + ", "
            column = column[:-2]
            column += "'"
            filterSelectDataVector(vector_file_cut,
                                   vector_file_filter,
                                   column,
                                   sql_filter,
                                   overwrite=overwrite,
                                   format_vector=format_vector)
        else:
            vector_file_filter = vector_file_cut

        # Application d'un tampon (facultatif)
        if buffer_len != '' and buffer_len != 0:
            if debug >= 3:
                print(cyan + "vectorsListToOcs() : " + endC +
                      "Application d'un buffer : %s." % buffer_len + '\n')
            if type(buffer_len) is float:
                bufferVector(vector_file_filter,
                             vector_file_buffer,
                             buffer_len,
                             col_name_buf='',
                             fact_buf=1.0,
                             quadsecs=10,
                             format_vector=format_vector)
            else:
                bufferVector(vector_file_filter,
                             vector_file_buffer,
                             0,
                             col_name_buf=buffer_len,
                             fact_buf=1.0,
                             quadsecs=10,
                             format_vector=format_vector)
        else:
            vector_file_buffer = vector_file_filter

        # Rastérisation du vecteur préparé
        if debug >= 3:
            print(cyan + "vectorsListToOcs() : " + endC +
                  "Rastérisation du vecteur préparé." + '\n')
        rasterizeBinaryVector(vector_file_buffer,
                              reference_raster,
                              vector_file_raster,
                              label=class_label,
                              codage=codage_raster)

        # Ajout de l'information dans le raster de sortie
        if debug >= 3:
            print(cyan + "vectorsListToOcs() : " + endC +
                  "Ajout de l'information dans le raster de sortie." + '\n')
        if idx == 1:
            shutil.copy(vector_file_raster, output_raster)
        else:
            removeFile(temp_raster)
            shutil.copy(output_raster, temp_raster)
            removeFile(output_raster)
            expression = "im1b1!=%s ? im1b1 : im2b1" % no_data_value
            rasterCalculator([temp_raster, vector_file_raster],
                             output_raster,
                             expression,
                             codage=codage_raster)

    print(cyan + "vectorsListToOcs() : " + bold + green +
          "Fin de la génération de l'OCS raster à partir de vecteurs." + endC +
          '\n')

    ####################################################################

    # Suppression des fichiers temporaires
    if not save_results_intermediate:
        if debug >= 3:
            print(cyan + "vectorsListToOcs() : " + endC +
                  "Suppression des fichiers temporaires." + '\n')
        deleteDir(temp_directory)

    print(cyan + "vectorsListToOcs() : " + bold + green +
          "FIN DES TRAITEMENTS" + endC + '\n')

    # Mise à jour du log
    ending_event = "vectorsListToOcs() : Fin du traitement : "
    timeLine(path_time_log, ending_event)

    return 0
def processTDCfilesSmoothAndFusion(coastline_vectors_input_list, vector_rocky_input, vector_all_output, vector_withrocky_output, generalize_param_method, generalize_param_threshold, name_column_fusion, path_time_log, epsg=2154, format_vector='ESRI Shapefile', extension_vector='.shp', save_results_intermediate=False, overwrite=True):

    # Mise à jour du Log
    starting_event = "processTDCfilesSmoothAndFusion() : Create final coastline starting : "
    timeLine(path_time_log,starting_event)

    print(endC)
    print(bold + green + "## START : POST TRAITEMENT TDC" + endC)
    print(endC)

    if debug >= 2:
        print(bold + green + "processTDCfilesSmoothAndFusion() : Variables dans la fonction" + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "coastline_vectors_input_list : " + str(coastline_vectors_input_list) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "vector_rocky_input : " + str(vector_rocky_input) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "vector_all_output : " + str(vector_all_output) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "vector_withrocky_output : " + str(vector_withrocky_output) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "generalize_param_method : " + str(generalize_param_method) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "generalize_param_threshold : " + str(generalize_param_threshold) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "name_column_fusion : " + str(name_column_fusion) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "epsg : " + str(epsg) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "format_vector : " + str(format_vector) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "extension_vector : " + str(extension_vector) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "path_time_log : " + str(path_time_log) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "save_results_intermediate : " + str(save_results_intermediate) + endC)
        print(cyan + "processTDCfilesSmoothAndFusion() : " + endC + "overwrite : " + str(overwrite) + endC)

    SUFFIX_SMOOTH = "_smooth"
    SUFFIX_TMP = "_tmp"
    SUFFIX_SMOOTH = "_smooth"
    SUFFIX_FUSION = "_fusion"

    repertory_output = os.path.dirname(vector_all_output)
    file_name = os.path.splitext(os.path.basename(vector_all_output))[0]
    vector_fusion = repertory_output + os.sep + file_name + SUFFIX_FUSION + extension_vector

    repertory_temp = repertory_output + os.sep + file_name + SUFFIX_TMP
    if not os.path.exists(repertory_temp):
        os.makedirs(repertory_temp)

    # Vérification de l'existence du vecteur de sortie
    check = os.path.isfile(vector_all_output)

    # Si oui et si la vérification est activée, passage à l'étape suivante
    if check and not overwrite :
        print(cyan + "processTDCfilesSmoothAndFusion() : " + bold + green +  "Vector general coastline already existe : " + str(vector_all_output) + "." + endC)
    # Si non ou si la vérification est désactivée, application des traitements de lissage et de la fusion
    else:
        # Tentative de suppresion des fichiers
        try:
            removeVectorFile(vector_all_output)
            removeVectorFile(vector_withrocky_output)
        except Exception:
            # Ignore l'exception levée si le fichier n'existe pas (et ne peut donc pas être supprimé)
            pass

        # Pour tous les fichiers vecteurs d'entrée appliquer le traitement de lissage par GRASS
        param_generalize_dico = {"method":generalize_param_method, "threshold":generalize_param_threshold}
        vectors_temp_output_list = []

        for input_vector in coastline_vectors_input_list :
            vector_name = os.path.splitext(os.path.basename(input_vector))[0]
            output_temp_vector = repertory_temp + os.sep + vector_name + SUFFIX_TMP + extension_vector
            output_smooth_vector = repertory_temp + os.sep + vector_name + SUFFIX_SMOOTH + extension_vector

            vectors_temp_output_list.append(output_temp_vector)
            xmin, xmax, ymin, ymax = getEmpriseFile(input_vector, format_vector)
            projection = getProjection(input_vector, format_vector)
            if projection is None:
                projection = epsg

            # Init GRASS
            if debug >= 3:
                print(cyan + "processTDCfilesSmoothAndFusion() : " + bold + green +  "Initialisation de GRASS " + endC)
            initializeGrass(repertory_temp, xmin, xmax, ymin, ymax, 1, 1, projection)

            # Generalize GRASS
            if debug >= 3:
                print(cyan + "processTDCfilesSmoothAndFusion() : " + bold + green +  "Applying smooth GRASS for vector : " + str(input_vector) + endC)
            smoothGeomGrass(input_vector, output_smooth_vector, param_generalize_dico, format_vector, overwrite)
            geometries2multigeometries(output_smooth_vector, output_temp_vector, name_column_fusion, format_vector)

            # Init GRASS
            if debug >= 3:
                print(cyan + "processTDCfilesSmoothAndFusion() : " + bold + green +  "Cloture de GRASS " + endC)
            cleanGrass(repertory_temp)

        if debug >= 3:
            print(cyan + "processTDCfilesSmoothAndFusion() : " + bold + green +  "Fusion de tous les vecteurs lissés : " + str(vectors_temp_output_list) + endC)

        # Fusion de tous les fichiers vecteurs temp
        fusionVectors(vectors_temp_output_list, vector_fusion, format_vector)

        # Suppression du champ "cat" introduit par l'application GRASS
        deleteFieldsVector(vector_fusion, vector_all_output, ["cat"], format_vector)

        # Re-met à jour le champ id avec un increment
        updateIndexVector(vector_all_output, "id", format_vector)

        # Nettoyage des zones rocheuses sur la ligne de trait de côte
        if vector_rocky_input != "" and vector_withrocky_output != "":
            if debug >= 3:
                print("\n" + cyan + "processTDCfilesSmoothAndFusion() : " + bold + green +  "Creation d'un trait de côte generale sans les zones rocheuses : " + str(vector_withrocky_output) + endC)
            differenceVector(vector_rocky_input, vector_all_output, vector_withrocky_output, overwrite, format_vector)

    # Suppression des fichiers intermédiaires
    if not save_results_intermediate :
        if debug >= 3:
            print(cyan + "processTDCfilesSmoothAndFusion() : " + bold + green +  "Suppression des fichiers temporaires " + endC)
        if os.path.exists(repertory_temp):
            shutil.rmtree(repertory_temp)
        removeVectorFile(vector_fusion)

    print(endC)
    print(bold + green + "## END :  POST TRAITEMENT TDC" + endC)
    print(endC)

    # Mise à jour du Log
    ending_event = "processTDCfilesSmoothAndFusion() : Create final coastline ending : "
    timeLine(path_time_log,ending_event)

    return
def cutRasterImages(images_input_list,
                    vector_cut,
                    images_output_list,
                    buffer_size,
                    round_pixel_size,
                    epsg,
                    no_data_value,
                    resampling_methode,
                    z_compress,
                    path_time_log,
                    format_raster='GTiff',
                    format_vector='ESRI Shapefile',
                    extension_raster=".tif",
                    extension_vector=".shp",
                    save_results_intermediate=False,
                    overwrite=True):

    # Mise à jour du Log
    starting_event = "cutRasterImages() : Cutting rasters and vector starting : "
    timeLine(path_time_log, starting_event)

    print(endC)
    print(bold + green + "## START : CUTTING IMAGES" + endC)
    print(endC)

    if debug >= 2:
        print(bold + green + "cutRasterImages() : Variables dans la fonction" +
              endC)
        print(cyan + "cutRasterImages() : " + endC + "images_input_list : " +
              str(images_input_list) + endC)
        print(cyan + "cutRasterImages() : " + endC + "vector_cut : " +
              str(vector_cut) + endC)
        print(cyan + "cutRasterImages() : " + endC + "images_output_list : " +
              str(images_output_list) + endC)
        print(cyan + "cutRasterImages() : " + endC + "buffer_size : " +
              str(buffer_size) + endC)
        print(cyan + "cutRasterImages() : " + endC + "round_pixel_size : " +
              str(round_pixel_size) + endC)
        print(cyan + "cutRasterImages() : " + endC + "epsg : " + str(epsg) +
              endC)
        print(cyan + "cutRasterImages() : " + endC + "no_data_value : " +
              str(no_data_value) + endC)
        print(cyan + "cutRasterImages() : " + endC + "resampling_methode : " +
              str(resampling_methode))
        print(cyan + "cutRasterImages() : " + endC + "z_compress : " +
              str(z_compress))
        print(cyan + "cutRasterImages() : " + endC + "path_time_log : " +
              str(path_time_log) + endC)
        print(cyan + "cutRasterImages() : " + endC + "format_raster : " +
              str(format_raster) + endC)
        print(cyan + "cutRasterImages() : " + endC + "format_vector : " +
              str(format_vector) + endC)
        print(cyan + "cutRasterImages() : " + endC + "extension_raster : " +
              str(extension_raster) + endC)
        print(cyan + "cutRasterImages() : " + endC + "extension_vector : " +
              str(extension_vector) + endC)
        print(cyan + "cutRasterImages() : " + endC +
              "save_results_intermediate : " + str(save_results_intermediate) +
              endC)
        print(cyan + "cutRasterImages() : " + endC + "overwrite : " +
              str(overwrite) + endC)

    # PREPARATION DES FICHIERS INTERMEDIAIRES
    BUFF_SUFFIX = "_buf"
    CUT_SUFFIX = "_cut"
    COMPRESS_SUFFIX = "_compress"

    EPSG_DEFAULT = 2154

    if buffer_size > 0 and len(
            images_input_list
    ) > 0:  # Cas le vecteur de découpe des rasteurs est bufferisé
        vector_buf_for_raster_cut = os.path.splitext(
            vector_cut)[0] + BUFF_SUFFIX + str(int(round(
                buffer_size, 0))) + 'm' + extension_vector
        if debug >= 3:
            print("vector_buf_for_raster_cut : " +
                  str(vector_buf_for_raster_cut) + endC)

        # Test si le vecteur decoupe existe déjà et si il doit être écrasés
        check = os.path.isfile(vector_buf_for_raster_cut)

        if check and not overwrite:  # Si le fichier existe deja et que overwrite n'est pas activé
            print(bold + yellow + "File vector cutting : " +
                  vector_buf_for_raster_cut +
                  " already exists and will not be created again." + endC)
        else:
            if check:
                try:
                    removeVectorFile(vector_buf_for_raster_cut)
                except Exception:
                    pass  # si le fichier n'existe pas, il ne peut pas être supprimé : cette étape est ignorée

            # Création du vecteur de découpe bufferisé
            bufferVector(vector_cut, vector_buf_for_raster_cut, buffer_size,
                         "", 1.0, 10, format_vector)

    else:  # Cas le vecteur de découpe des rasteurs n'est pas bufferisé idem vecteur de découpe que les vecteurs
        vector_buf_for_raster_cut = vector_cut

    # DECOUPAGE DES RASTEURS PAR LE VECTEUR DE DECOUPE

    # Pour tous les fichiers raster à découpper
    for index_raster in range(len(images_input_list)):

        # Préparation des rasters de travail d'entrée et de sortie
        raster_input = images_input_list[index_raster]
        raster_output = images_output_list[index_raster]
        raster_output_compress = os.path.splitext(
            raster_output)[0] + COMPRESS_SUFFIX + extension_raster
        vector_cut_temp = os.path.splitext(
            raster_output)[0] + CUT_SUFFIX + extension_vector

        if debug >= 1:
            print("\n")
            print(cyan + "cutRasterImages() : " + endC + bold + green +
                  "Découpe fichier raster : " + endC + str(raster_input) +
                  endC)

        # Récuperation de l'emprise de l'image
        ima_xmin, ima_xmax, ima_ymin, ima_ymax = getEmpriseImage(raster_input)

        # Recuperation de la valeur de l'arrondi de la taille des pixels en X et Y si non définie
        if round_pixel_size == 0.0 and os.path.isfile(raster_input):
            # Identification de la tailles de pixels en x et en y
            pixel_size_x, pixel_size_y = getPixelWidthXYImage(raster_input)
            round_pixel_size = abs(pixel_size_x)
        else:
            pixel_size_x = round_pixel_size
            pixel_size_y = round_pixel_size

        # Préparation du vecteur de découpe temporaire
        createEmpriseShapeReduced(vector_buf_for_raster_cut, ima_xmin,
                                  ima_ymin, ima_xmax, ima_ymax,
                                  vector_cut_temp, format_vector)

        # Identification de l'emprise de vecteur de découpe
        empr_xmin, empr_xmax, empr_ymin, empr_ymax = getEmpriseFile(
            vector_cut_temp, format_vector)

        # Calculer l'emprise arrondi
        xmin, xmax, ymin, ymax = roundPixelEmpriseSize(pixel_size_x,
                                                       pixel_size_y, empr_xmin,
                                                       empr_xmax, empr_ymin,
                                                       empr_ymax)

        # Trouver l'emprise optimale
        opt_xmin = xmin
        opt_xmax = xmax
        opt_ymin = ymin
        opt_ymax = ymax

        if ima_xmin > xmin:
            opt_xmin = ima_xmin
        if ima_xmax < xmax:
            opt_xmax = ima_xmax
        if ima_ymin > ymin:
            opt_ymin = ima_ymin
        if ima_ymax < ymax:
            opt_ymax = ima_ymax

        # Récuperation de la projection de l'image
        if epsg == 0:
            epsg_proj = getProjectionImage(raster_input)
        else:
            epsg_proj = epsg
        if epsg_proj == 0:
            epsg_proj = EPSG_DEFAULT

        if debug >= 3:
            print("epsg : " + str(epsg_proj) + endC)
            print("\n")

        # Test si le rasteur de sortie existe déjà et si il doit être écrasés
        check = os.path.isfile(raster_output)

        if check and not overwrite:  # Si le fichier existe deja et que overwrite n'est pas activé
            print(bold + yellow + "File raster output : " + raster_output +
                  " already exists and will not be created again." + endC)
        else:
            if check:
                try:
                    removeFile(raster_output)
                except Exception:
                    pass  # si le fichier n'existe pas, il ne peut pas être supprimé : cette étape est ignorée

            # Commande de découpe raster
            command = 'gdalwarp -t_srs EPSG:' + str(epsg_proj) + ' -te ' + str(
                opt_xmin
            ) + ' ' + str(opt_ymin) + ' ' + str(opt_xmax) + ' ' + str(
                opt_ymax
            ) + ' -tap -multi -co "NUM_THREADS=ALL_CPUS" -dstnodata ' + str(
                no_data_value
            ) + ' -tr ' + str(abs(pixel_size_x)) + ' ' + str(
                abs(pixel_size_y)
            ) + ' -cutline ' + vector_cut_temp + ' -of ' + format_raster + ' ' + raster_input + ' ' + raster_output

            if resampling_methode != "":
                command += " -r " + resampling_methode

            if overwrite:
                command += ' -overwrite'

            if debug >= 2:
                print(bold + green + "Command : " + command + endC)
            exit_code = os.system(command)
            if exit_code != 0:
                print(
                    cyan + "cutRasterImages() : " + bold + red +
                    "!!! Une erreur c'est produite au cours du decoupage de l'image : "
                    + raster_input + ". Voir message d'erreur." + endC,
                    file=sys.stderr)
                raise
            if debug >= 2:
                print(cyan + "cutRasterImages() : " + bold + green +
                      "DECOUPAGE DU RASTER %s AVEC LE VECTEUR %s" %
                      (raster_input, vector_buf_for_raster_cut) + endC)
                print(command)

            if z_compress:
                # Commande de découpe raster et compression
                command = 'gdalwarp -t_srs EPSG:' + str(
                    epsg_proj
                ) + ' -te ' + str(opt_xmin) + ' ' + str(opt_ymin) + ' ' + str(
                    opt_xmax
                ) + ' ' + str(
                    opt_ymax
                ) + ' -tap -multi -co "NUM_THREADS=ALL_CPUS" -dstnodata ' + str(
                    no_data_value
                ) + ' -tr ' + str(abs(pixel_size_x)) + ' ' + str(
                    abs(pixel_size_y)
                ) + ' -co "COMPRESS=DEFLATE" -co "PREDICTOR=2" -co "ZLEVEL=9" -cutline ' + vector_cut_temp + ' -of ' + format_raster + ' ' + raster_input + ' ' + raster_output_compress

                if resampling_methode != "":
                    command += ' -r ' + resampling_methode

                if overwrite:
                    command += ' -overwrite'

                if debug >= 2:
                    print(bold + green + "Command : " + command + endC)
                exit_code = os.system(command)
                if exit_code != 0:
                    print(
                        cyan + "cutRasterImages() : " + bold + red +
                        "!!! Une erreur c'est produite au cours du decoupage de l'image : "
                        + raster_input + ". Voir message d'erreur." + endC,
                        file=sys.stderr)
                    raise
                if debug >= 2:
                    print(
                        cyan + "cutRasterImages() : " + bold + green +
                        "DECOUPAGE ET COMPRESSION DU RASTER %s AVEC LE VECTEUR %s"
                        % (raster_input, vector_buf_for_raster_cut) + endC)
                    print(command)

        # Suppression des fichiers intermédiaires
        removeVectorFile(vector_cut_temp)

    # SUPPRESIONS FICHIERS INTERMEDIAIRES INUTILES

    # Suppression des fichiers intermédiaires
    if not save_results_intermediate and os.path.isfile(
            vector_buf_for_raster_cut
    ) and vector_buf_for_raster_cut != vector_cut:
        removeVectorFile(vector_buf_for_raster_cut)

    print(endC)
    print(bold + green + "## END : CUTTING IMAGES" + endC)
    print(endC)

    # Mise à jour du Log
    ending_event = "cutRasterImages() : Cutting rasters and vector  ending : "
    timeLine(path_time_log, ending_event)

    return
Пример #6
0
def terrainRoughnessClass(grid_input, grid_output, built_input, distance_lines, epsg, project_encoding, server_postgis, port_number, user_postgis, password_postgis, database_postgis, schema_postgis, path_time_log, format_vector='ESRI Shapefile', save_results_intermediate=False, overwrite=True):

    print(bold + yellow + "Début du calcul de l'indicateur Terrain Roughness Class." + endC + "\n")
    timeLine(path_time_log, "Début du calcul de l'indicateur Terrain Roughness Class : ")

    if debug >= 3:
        print(bold + green + "terrainRoughnessClass() : Variables dans la fonction" + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "grid_input : " + str(grid_input) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "grid_output : " + str(grid_output) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "built_input : " + str(built_input) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "distance_lines : " + str(distance_lines) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "epsg : " + str(epsg) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "project_encoding : " + str(project_encoding) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "server_postgis : " + str(server_postgis) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "port_number : " + str(port_number) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "user_postgis : " + str(user_postgis) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "password_postgis : " + str(password_postgis) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "database_postgis : " + str(database_postgis) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "schema_postgis : " + str(schema_postgis) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "path_time_log : " + str(path_time_log) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "format_vector : " + str(format_vector) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "save_results_intermediate : " + str(save_results_intermediate) + endC)
        print(cyan + "terrainRoughnessClass() : " + endC + "overwrite : " + str(overwrite) + endC)
        print("\n")

    if not os.path.exists(grid_output) or overwrite:

        ############################################
        ### Préparation générale des traitements ###
        ############################################

        print(bold + cyan + "Préparation au calcul de Terrain Roughness Class :" + endC)
        timeLine(path_time_log, "    Préparation au calcul de Terrain Roughness Class : ")

        if os.path.exists(grid_output):
            removeVectorFile(grid_output)

        # Création de la base de données PostGIS
        # ~ dropDatabase(database_postgis, user_name=user_postgis, password=password_postgis, ip_host=server_postgis, num_port=port_number, schema_name=schema_postgis) # Conflits avec autres indicateurs (Aspect Ratio / Height of Roughness Elements)
        createDatabase(database_postgis, user_name=user_postgis, password=password_postgis, ip_host=server_postgis, num_port=port_number, schema_name=schema_postgis)

        # Import des fichiers shapes maille et bati dans la base de données PostGIS
        table_name_maille = importVectorByOgr2ogr(database_postgis, grid_input, 'trc_maille', user_name=user_postgis, password=password_postgis, ip_host=server_postgis, num_port=str(port_number), schema_name=schema_postgis, epsg=str(epsg), codage=project_encoding)
        table_name_bati = importVectorByOgr2ogr(database_postgis, built_input, 'trc_bati', user_name=user_postgis, password=password_postgis, ip_host=server_postgis, num_port=str(port_number), schema_name=schema_postgis, epsg=str(epsg), codage=project_encoding)

        # Récupération de l'emprise de la zone d'étude, définie par le fichier maillage d'entrée
        xmin,xmax,ymin,ymax = getEmpriseFile(grid_input, format_vector)
        if debug >= 1:
            print(bold + "Emprise du fichier '%s' :" % (grid_input) + endC)
            print("    xmin = " + str(xmin))
            print("    xmax = " + str(xmax))
            print("    ymin = " + str(ymin))
            print("    ymax = " + str(ymax))

        # Création de la liste des valeurs de x à entrer dans la requêtes SQL de création de lignes
        x_list = [xmin] # Initialisation de la liste
        x = xmin # Définition de la valeur du 1er x à entrer dans la boucle
        while x < (xmax - distance_lines): # On boucle tant que la valeur de x ne dépasse pas le xmax du fichier maillage en entrée
            x = x + distance_lines
            x_list.append(x) # Ajout de la nouvelle valeur de x dans la liste
        if debug >= 2:
            print(bold + "x_list : "  + endC + str(x_list) + "\n")

        # Création de la liste des valeurs de y à entrer dans la requêtes SQL de création de lignes
        y_list = [ymax] # Initialisation de la liste
        y = ymax # Définition de la valeur du 1er y à entrer dans la boucle
        while y > (ymin + distance_lines): # On boucle tant que la valeur de y ne descend pas en-dessous du ymin du fichier maillage en entrée
            y = y - distance_lines
            y_list.append(y) # Ajout de la nouvelle valeur de y dans la liste
        if debug >= 2:
            print(bold + "y_list : "  + endC + str(y_list) + "\n")

        #################################################
        ### Création des lignes parallèles N-S et W-E ###
        #################################################

        print(bold + cyan + "Création des lignes parallèles N-S et W-E :" + endC)
        timeLine(path_time_log, "    Création des lignes parallèles N-S et W-E : ")

        connection = openConnection(database_postgis, user_name=user_postgis, password=password_postgis, ip_host=server_postgis, num_port=port_number, schema_name=schema_postgis)

        # Construction de la requête de création des lignes parallèles N-S
        query_lines_NS = "DROP TABLE IF EXISTS trc_lines_NS;\n"
        query_lines_NS += "CREATE TABLE trc_lines_NS (line text, geom geometry);\n"
        query_lines_NS += "INSERT INTO trc_lines_NS VALUES\n"

        # Boucle sur les valeurs de x dans la liste associée, pour construire la requête de création des lignes parallèles N-S
        count_NS = 0
        for x in x_list:
            count_NS += 1
            query_lines_NS += "    ('line_NS_%s', 'LINESTRING(%s %s, %s %s)'),\n" % (count_NS, x, ymax, x, ymin)

        # Fin de la requête de création des lignes parallèles N-S et exécution de cette requête
        query_lines_NS = query_lines_NS[:-2] + ";\n" # Transformer la virgule de la dernière ligne SQL en point-virgule (pour terminer la requête)
        query_lines_NS += "ALTER TABLE trc_lines_NS ALTER COLUMN geom TYPE geometry(LINESTRING,%s) USING ST_SetSRID(geom,%s);\n" % (epsg,epsg) # Mise à jour du système de coordonnées
        if debug >= 1:
            print(query_lines_NS)
        executeQuery(connection, query_lines_NS)

        # Construction de la requête de création des lignes parallèles W-E
        query_lines_WE = "DROP TABLE IF EXISTS trc_lines_WE;\n"
        query_lines_WE += "CREATE TABLE trc_lines_WE (line text, geom geometry);\n"
        query_lines_WE += "INSERT INTO trc_lines_WE VALUES\n"

        # Boucle sur les valeurs de y dans la liste associée, pour construire la requête de création des lignes parallèles W-E
        count_WE = 0
        for y in y_list:
            count_WE += 1
            query_lines_WE += "    ('line_WE_%s', 'LINESTRING(%s %s, %s %s)'),\n" % (count_WE, xmin, y, xmax, y)

        # Fin de la requête de création des lignes parallèles W-E et exécution de cette requête
        query_lines_WE = query_lines_WE[:-2] + ";\n" # Transformer la virgule de la dernière ligne SQL en point-virgule (pour terminer la requête)
        query_lines_WE += "ALTER TABLE trc_lines_WE ALTER COLUMN geom TYPE geometry(LINESTRING,%s) USING ST_SetSRID(geom,%s);\n" % (epsg,epsg) # Mise à jour du système de coordonnées

        if debug >= 1:
            print(query_lines_WE)
        executeQuery(connection, query_lines_WE)

        #####################################################################################################
        ### Découpage des bâtiments, et des lignes N-S et W-E à cheval sur plusieurs mailles (intersects) ###
        #####################################################################################################

        print(bold + cyan + "Lancement des requêtes d'intersect :" + endC)
        timeLine(path_time_log, "    Lancement des requêtes d'intersect : ")

        query_intersect = """
        --CREATE INDEX IF NOT EXISTS maille_geom_gist ON %s USING GIST (geom);
        --CREATE INDEX IF NOT EXISTS bati_geom_gist ON %s USING GIST (geom);
        CREATE INDEX IF NOT EXISTS lines_NS_geom_gist ON trc_lines_NS USING GIST (geom);
        CREATE INDEX IF NOT EXISTS lines_WE_geom_gist ON trc_lines_WE USING GIST (geom);

        DROP TABLE IF EXISTS trc_decoup;
        CREATE TABLE trc_decoup AS
            SELECT b.ID as ID, b.HAUTEUR as hauteur, ST_Intersection(b.geom, m.geom) as geom
            FROM %s as b, %s as m
            WHERE ST_Intersects(b.geom, m.geom);
        CREATE INDEX IF NOT EXISTS decoup_geom_gist ON trc_decoup USING GIST (geom);

        DROP TABLE IF EXISTS trc_decoupNS;
        CREATE TABLE trc_decoupNS AS
            SELECT m.ID as ID, l.line as line, ST_Intersection(l.geom, m.geom) as geom
            FROM trc_lines_NS as l, %s as m
            WHERE ST_Intersects(l.geom, m.geom);
        CREATE INDEX IF NOT EXISTS decoupNS_geom_gist ON trc_decoupNS USING GIST (geom);

        DROP TABLE IF EXISTS trc_decoupWE;
        CREATE TABLE trc_decoupWE AS
            SELECT m.ID as ID, l.line as line, ST_Intersection(l.geom, m.geom) as geom
            FROM trc_lines_WE as l, %s as m
            WHERE ST_Intersects(l.geom, m.geom);
        CREATE INDEX IF NOT EXISTS decoupWE_geom_gist ON trc_decoupWE USING GIST (geom);
        """ % (table_name_maille, table_name_bati, table_name_bati, table_name_maille, table_name_maille, table_name_maille)

        if debug >= 1:
            print(query_intersect)
        executeQuery(connection, query_intersect)

        #######################################################################################################################################################
        ### Calculs pour l'obtention des sous-indicateurs liés à l'intersect des bâtiments dans chaque maille :  h, plan area ratio, hauteur de déplacement ###
        #######################################################################################################################################################

        print(bold + cyan + "Calcul des indicateurs secondaires liés aux bâtiments intersectant chaque maille :" + endC)
        timeLine(path_time_log, "    Calcul des indicateurs secondaires liés aux bâtiments intersectant chaque maille : ")

        query_bati = """
        DROP TABLE IF EXISTS trc_temp_a;
        CREATE TABLE trc_temp_a AS
            SELECT ID, hauteur, st_area(geom) as surface, geom
            FROM trc_decoup;
        ALTER TABLE trc_temp_a ADD volume DOUBLE PRECISION;
        UPDATE trc_temp_a SET volume = (surface * hauteur);
        ALTER TABLE trc_temp_a ADD VxH DOUBLE PRECISION;
        UPDATE trc_temp_a SET VxH = (volume * hauteur);
        CREATE INDEX IF NOT EXISTS temp_a_geom_gist ON trc_temp_a USING GIST (geom);

        DROP TABLE IF EXISTS trc_temp_b;
        CREATE TABLE trc_temp_b AS
            SELECT m.ID as ID, (sum(a.VxH) / sum(a.volume)) as h, (sum(a.surface) / st_area(m.geom)) as PAR, m.geom as geom
            FROM %s as m, trc_temp_a as a
            WHERE ST_Intersects(m.geom, a.geom)
            GROUP BY m.ID, m.geom;
        ALTER TABLE trc_temp_b ADD zd DOUBLE PRECISION;
        UPDATE trc_temp_b SET zd = (h * (PAR ^ 0.6));
        CREATE INDEX IF NOT EXISTS temp_b_geom_gist ON trc_temp_b USING GIST (geom);

        DROP TABLE IF EXISTS trc_temp_c;
        CREATE TABLE trc_temp_c AS
            SELECT DISTINCT ID, geom
            FROM %s
            WHERE ID NOT IN
                (SELECT DISTINCT ID
                FROM trc_temp_b);
        ALTER TABLE trc_temp_c ADD h DOUBLE PRECISION;
        UPDATE trc_temp_c SET h = 0;
        ALTER TABLE trc_temp_c ADD PAR DOUBLE PRECISION;
        UPDATE trc_temp_c SET PAR = 0;
        ALTER TABLE trc_temp_c ADD zd DOUBLE PRECISION;
        UPDATE trc_temp_c SET zd = 0;
        CREATE INDEX IF NOT EXISTS temp_c_geom_gist ON trc_temp_c USING GIST (geom);

        DROP TABLE IF EXISTS trc_temp;
        CREATE TABLE trc_temp AS
            SELECT ID, h, PAR, zd, geom
            FROM trc_temp_b
            UNION
            SELECT ID, h, PAR, zd, geom
            FROM trc_temp_c;
        ALTER TABLE trc_temp ALTER COLUMN ID TYPE INTEGER;
        CREATE INDEX IF NOT EXISTS temp_geom_gist ON trc_temp USING GIST (geom);
        """ % (table_name_maille, table_name_maille)

        if debug >= 1:
            print(query_bati)
        executeQuery(connection, query_bati)

        #####################################################################################################################################################
        ### Calculs pour l'obtention des sous-indicateurs liés à l'intersect des bâtiments avec chaque ligne N-S, dans chaque maille : frontal area ratio ###
        #####################################################################################################################################################

        print(bold + cyan + "Calcul des indicateurs secondaires liés aux bâtiments intersectant chaque ligne N-S, intersectant chaque maille :" + endC)
        timeLine(path_time_log, "    Calcul des indicateurs secondaires liés aux bâtiments intersectant chaque ligne N-S, intersectant chaque maille : ")

        query_NS = """
        DROP TABLE IF EXISTS trc_tempNS_a;
        CREATE TABLE trc_tempNS_a AS
            SELECT ns.ID as ID, ns.line as line, max(d.hauteur) as max_haut, (%s * max(d.hauteur)) as FA, ns.geom as geom
            FROM trc_decoup as d, trc_decoupNS as ns
            WHERE ST_Intersects(d.geom, ns.geom)
            GROUP BY ns.ID, ns.line, ns.geom;
        CREATE INDEX IF NOT EXISTS tempNS_a_geom_gist ON trc_tempNS_a USING GIST (geom);

        DROP TABLE IF EXISTS trc_tempNS_b;
        CREATE TABLE trc_tempNS_b AS
            SELECT m.ID as ID, (sum(a.FA) / st_area(m.geom)) as FAR, m.geom as geom
            FROM trc_tempNS_a as a, %s as m
            WHERE ST_Intersects(a.geom, m.geom)
            GROUP BY m.ID, m.geom;
        CREATE INDEX IF NOT EXISTS tempNS_b_geom_gist ON trc_tempNS_b USING GIST (geom);

        DROP TABLE IF EXISTS trc_tempNS_c;
        CREATE TABLE trc_tempNS_c AS
            SELECT DISTINCT ID, geom
            FROM %s
            WHERE ID NOT IN
                (SELECT DISTINCT ID
                FROM trc_tempNS_b);
        ALTER TABLE trc_tempNS_c ADD FAR DOUBLE PRECISION;
        UPDATE trc_tempNS_c SET FAR = 0;
        CREATE INDEX IF NOT EXISTS tempNS_c_geom_gist ON trc_tempNS_c USING GIST (geom);

        DROP TABLE IF EXISTS trc_tempNS;
        CREATE TABLE trc_tempNS AS
            SELECT ID, FAR, geom
            FROM trc_tempNS_b
            UNION
            SELECT ID, FAR, geom
            FROM trc_tempNS_c;
        ALTER TABLE trc_tempNS ALTER COLUMN ID TYPE INTEGER;
        CREATE INDEX IF NOT EXISTS tempNS_geom_gist ON trc_tempNS USING GIST (geom);
        """ % (distance_lines, table_name_maille, table_name_maille)

        if debug >= 1:
            print(query_NS)
        executeQuery(connection, query_NS)

        #####################################################################################################################################################
        ### Calculs pour l'obtention des sous-indicateurs liés à l'intersect des bâtiments avec chaque ligne W-E, dans chaque maille : frontal area ratio ###
        #####################################################################################################################################################

        print(bold + cyan + "Calcul des indicateurs secondaires liés aux bâtiments intersectant chaque ligne W-E, intersectant chaque maille :" + endC)
        timeLine(path_time_log, "    Calcul des indicateurs secondaires liés aux bâtiments intersectant chaque ligne W-E, intersectant chaque maille : ")

        query_WE = """
        DROP TABLE IF EXISTS trc_tempWE_a;
        CREATE TABLE trc_tempWE_a AS
            SELECT we.ID as ID, we.line as line, max(d.hauteur) as max_haut, (%s * max(d.hauteur)) as FA, we.geom as geom
            FROM trc_decoup as d, trc_decoupWE as we
            WHERE ST_Intersects(d.geom, we.geom)
            GROUP BY we.ID, we.line, we.geom;
        CREATE INDEX IF NOT EXISTS tempWE_a_geom_gist ON trc_tempWE_a USING GIST (geom);

        DROP TABLE IF EXISTS trc_tempWE_b;
        CREATE TABLE trc_tempWE_b AS
            SELECT m.ID as ID, (sum(a.FA) / st_area(m.geom)) as FAR, m.geom as geom
            FROM trc_tempWE_a as a, %s as m
            WHERE ST_Intersects(a.geom, m.geom)
            GROUP BY m.ID, m.geom;
        CREATE INDEX IF NOT EXISTS tempWE_b_geom_gist ON trc_tempWE_b USING GIST (geom);

        DROP TABLE IF EXISTS trc_tempWE_c;
        CREATE TABLE trc_tempWE_c AS
            SELECT DISTINCT ID, geom
            FROM %s
            WHERE ID NOT IN
                (SELECT DISTINCT ID
                FROM trc_tempWE_b);
        ALTER TABLE trc_tempWE_c ADD FAR DOUBLE PRECISION;
        UPDATE trc_tempWE_c SET FAR = 0;
        CREATE INDEX IF NOT EXISTS tempWE_c_geom_gist ON trc_tempWE_c USING GIST (geom);

        DROP TABLE IF EXISTS trc_tempWE;
        CREATE TABLE trc_tempWE AS
            SELECT ID, FAR, geom
            FROM trc_tempWE_b
            UNION
            SELECT ID, FAR, geom
            FROM trc_tempWE_c;
        ALTER TABLE trc_tempWE ALTER COLUMN ID TYPE INTEGER;
        CREATE INDEX IF NOT EXISTS tempWE_geom_gist ON trc_tempWE USING GIST (geom);
        """ % (distance_lines, table_name_maille, table_name_maille)

        if debug >= 1:
            print(query_WE)
        executeQuery(connection, query_WE)

        ########################################################################################################################
        ### Calculs finaux pour l'obtention de l'indicateur de classe de rugosité : longueur de rugosité, classe de rugosité ###
        ########################################################################################################################

        print(bold + cyan + "Calculs finaux de l'indicateur de classe de rugosité :" + endC)
        timeLine(path_time_log, "    Calculs finaux de l'indicateur de classe de rugosité : ")

        query_rugo = """
        DROP TABLE IF EXISTS trc_rugo;
        CREATE TABLE trc_rugo AS
            SELECT t.ID as ID, t.h as h, t.PAR as PAR, t.zd as zd, ns.FAR as FAR_NS, we.FAR as FAR_WE, t.geom as geom
            FROM trc_temp as t, trc_tempNS as ns, trc_tempWE as we
            WHERE t.ID = ns.ID and ns.ID = WE.ID;
        ALTER TABLE trc_rugo ALTER COLUMN ID TYPE INTEGER;

        ALTER TABLE trc_rugo ADD COLUMN z0_NS DOUBLE PRECISION;
        UPDATE trc_rugo SET z0_NS = ((h - zd) * exp(-sqrt(0.4 / FAR_NS))) WHERE FAR_NS > 0;
        UPDATE trc_rugo SET z0_NS = 0 WHERE FAR_NS = 0;

        ALTER TABLE trc_rugo ADD COLUMN z0_WE DOUBLE PRECISION;
        UPDATE trc_rugo SET z0_WE = ((h - zd) * exp(-sqrt(0.4 / FAR_WE))) WHERE FAR_WE > 0;
        UPDATE trc_rugo SET z0_WE = 0 WHERE FAR_WE = 0;

        ALTER TABLE trc_rugo ADD COLUMN mean_z0 DOUBLE PRECISION;
        UPDATE trc_rugo SET mean_z0 = (z0_NS + z0_WE) / 2;

        ALTER TABLE trc_rugo ADD COLUMN cl_rugo integer;
        UPDATE trc_rugo SET cl_rugo = 1 WHERE mean_z0 < 0.0025;
        UPDATE trc_rugo SET cl_rugo = 2 WHERE mean_z0 >= 0.0025 and mean_z0 < 0.0175;
        UPDATE trc_rugo SET cl_rugo = 3 WHERE mean_z0 >= 0.0175 and mean_z0 < 0.065;
        UPDATE trc_rugo SET cl_rugo = 4 WHERE mean_z0 >= 0.065 and mean_z0 < 0.175;
        UPDATE trc_rugo SET cl_rugo = 5 WHERE mean_z0 >= 0.175 and mean_z0 < 0.375;
        UPDATE trc_rugo SET cl_rugo = 6 WHERE mean_z0 >= 0.375 and mean_z0 < 0.75;
        UPDATE trc_rugo SET cl_rugo = 7 WHERE mean_z0 >= 0.75 and mean_z0 < 1.5;
        UPDATE trc_rugo SET cl_rugo = 8 WHERE mean_z0 >= 1.5;
        """

        if debug >= 1:
            print(query_rugo)
        executeQuery(connection, query_rugo)
        closeConnection(connection)
        exportVectorByOgr2ogr(database_postgis, grid_output, 'trc_rugo', user_name=user_postgis, password=password_postgis, ip_host=server_postgis, num_port=str(port_number), schema_name=schema_postgis, format_type=format_vector)

        ##########################################
        ### Nettoyage des fichiers temporaires ###
        ##########################################

        if not save_results_intermediate:
            # ~ dropDatabase(database_postgis, user_name=user_postgis, password=password_postgis, ip_host=server_postgis, num_port=port_number, schema_name=schema_postgis) # Conflits avec autres indicateurs (Aspect Ratio / Height of Roughness Elements)
            pass

    else:
        print(bold + magenta + "Le calcul de Terrain Roughness Class a déjà eu lieu." + endC)

    print(bold + yellow + "Fin du calcul de l'indicateur Terrain Roughness Class." + endC + "\n")
    timeLine(path_time_log, "Fin du calcul de l'indicateur Terrain Roughness Class : ")

    return