Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Algorithmes et structures de données Discussion :

Algorithme traçage automatique Python Tkinter


Sujet :

Algorithmes et structures de données

  1. #1
    Nouveau membre du Club
    Algorithme traçage automatique Python Tkinter
    Bonjour à tous,

    Je me tourne vers vous pour avoir des conseils.

    J'essaie de faire un programme qui automatise un dessin, peu importe les postions de départ de x,y.

    Je m'explique, je récupère des coordonnées dans un fichier.txt de cette façon:

    165, 125
    165, 265
    365, 265
    365, 345
    525, 345
    525, 265
    625, 265
    625, 165
    525, 165
    525, 125
    185, 125

    Je dessine la première forme complète avec ma boucle while ( qui fonctionne bien ). Après, il faut que je reparte de cette forme pour faire quelque chose de similaire au dessin ci dessous, avec un décalage de 20 pixels.



    Le dessin ci dessus étant relativement simple et sans contrainte.

    Ci dessous un dessin plus compliqué ( exemple du programme )



    Plus compliqué car dans la zone en vert, elle n’apparaît plus dans la forme suivante car l'écart de 20 pixels n'est pas respecté. Donc on ne dessine pas les trois lignes.

    Voici le code actuellement de la partie du programme concerné. ( et encore il me manque le petit retour à chaque ligne, entouré en vert ).




    Code python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    from tkinter import *
     
    # Fenêtre
    root = Tk()
    Largeur = 1200
    Hauteur = 800
     
    canvas = Canvas(root, width=Largeur, height=Hauteur, background="white")
    canvas.pack(side=LEFT, padx=5, pady=5)
    root.resizable(width=False, height=False)
    root.title('Heating Draw')
     
    with open("valeur_x_y.txt", "r+") as file:
        liste_complet = file.readlines()
        liste_complet = ", ".join(liste_complet)
        liste_complet = liste_complet.replace("\n", "")
        liste_complet = liste_complet.split(", ")
        liste_complet = list(map(int, liste_complet))
        file.close()
     
    i = 0
     
    while(i <= len(liste_complet)-3):
        canvas.create_line(liste_complet[i], liste_complet[i+1], liste_complet[i+2], liste_complet[i+3], fill="red", width=3) # adding 1 to i for the next position
        i += 2
     
    canvas.create_line(liste_complet[0] + 20, liste_complet[1] + 20, liste_complet[2] + 20, liste_complet[3] - 20, fill="red", width=3)
    canvas.create_line(liste_complet[2] + 20, liste_complet[3] - 20, liste_complet[4] + 20, liste_complet[5] - 20, fill="red", width=3)
    canvas.create_line(liste_complet[4] + 20, liste_complet[5] - 20, liste_complet[6] + 20, liste_complet[7] - 20, fill="red", width=3)
    canvas.create_line(liste_complet[6] + 20, liste_complet[7] - 20, liste_complet[8] - 20, liste_complet[9] - 20, fill="red", width=3)
    canvas.create_line(liste_complet[8] - 20, liste_complet[9] - 20, liste_complet[10] - 20, liste_complet[11] - 20, fill="red", width=3)
    canvas.create_line(liste_complet[10] - 20, liste_complet[11] - 20, liste_complet[12] - 20, liste_complet[13] - 20, fill="red", width=3)
    canvas.create_line(liste_complet[12] - 20, liste_complet[13] - 20, liste_complet[14] - 20, liste_complet[15] + 20, fill="red", width=3)
    canvas.create_line(liste_complet[14] - 20, liste_complet[15] + 20, liste_complet[16] - 20, liste_complet[17] + 20, fill="red", width=3)
    canvas.create_line(liste_complet[16] - 20, liste_complet[17] + 20, liste_complet[18] - 20, liste_complet[19] + 20, fill="red", width=3)
    canvas.create_line(liste_complet[18] - 20, liste_complet[19] + 20, liste_complet[20] + 20, liste_complet[21] + 20, fill="red", width=3)
     
    canvas.create_line(liste_complet[0] + 40, liste_complet[1] + 40, liste_complet[2] + 40, liste_complet[3] - 40, fill="red", width=3)
    canvas.create_line(liste_complet[2] + 40, liste_complet[3] - 40, liste_complet[4] + 40, liste_complet[5] - 40, fill="red", width=3)
    canvas.create_line(liste_complet[4] + 40, liste_complet[5] - 40, liste_complet[6] + 40, liste_complet[7] - 40, fill="red", width=3)
    canvas.create_line(liste_complet[6] + 40, liste_complet[7] - 40, liste_complet[8] - 40, liste_complet[9] - 40, fill="red", width=3)
    canvas.create_line(liste_complet[8] - 40, liste_complet[9] - 40, liste_complet[10] - 40, liste_complet[11] - 40, fill="red", width=3)
    canvas.create_line(liste_complet[10] - 40, liste_complet[11] - 40, liste_complet[12] - 40, liste_complet[13] - 40, fill="red", width=3)
    canvas.create_line(liste_complet[12] - 40, liste_complet[13] - 40, liste_complet[14] - 40, liste_complet[15] + 40, fill="red", width=3)
    canvas.create_line(liste_complet[14] - 40, liste_complet[15] + 40, liste_complet[16] - 40, liste_complet[17] + 40, fill="red", width=3)
    canvas.create_line(liste_complet[16] - 40, liste_complet[17] + 40, liste_complet[18] - 40, liste_complet[19] + 40, fill="red", width=3)
    canvas.create_line(liste_complet[18] - 40, liste_complet[19] + 40, liste_complet[20] + 40, liste_complet[21] + 40, fill="red", width=3)
     
    canvas.create_line(liste_complet[0] + 60, liste_complet[1] + 60, liste_complet[2] + 60, liste_complet[3] - 60, fill="red", width=3)
    canvas.create_line(liste_complet[2] + 60, liste_complet[3] - 60, liste_complet[4] + 60, liste_complet[5] - 60, fill="red", width=3)
    canvas.create_line(liste_complet[4] + 60, liste_complet[5] - 60, liste_complet[6] + 60, liste_complet[7] - 60, fill="red", width=3)
    canvas.create_line(liste_complet[6] + 60, liste_complet[7] - 60, liste_complet[8] - 60, liste_complet[9] - 60, fill="red", width=3)
    canvas.create_line(liste_complet[8] - 60, liste_complet[9] - 60, liste_complet[10] - 60, liste_complet[11] - 60, fill="red", width=3)
    #canvas.create_line(liste_complet[10] - 60, liste_complet[11] - 60, liste_complet[12] - 60, liste_complet[13] - 60, fill="red", width=3)
    #canvas.create_line(liste_complet[12] - 60, liste_complet[13] - 60, liste_complet[14] - 60, liste_complet[15] + 60, fill="red", width=3)
    #canvas.create_line(liste_complet[14] - 60, liste_complet[15] + 60, liste_complet[16] - 60, liste_complet[17] + 60, fill="red", width=3)
    canvas.create_line(liste_complet[16] - 60, liste_complet[17] + 60, liste_complet[18] - 60, liste_complet[19] + 60, fill="red", width=3)
    canvas.create_line(liste_complet[18] - 60, liste_complet[19] + 60, liste_complet[20] + 60, liste_complet[21] + 60, fill="red", width=3)
     
    root.mainloop()



    Comme vous pouvez le remarqué, j'ai tapé toutes les lignes à la main pour comprendre comment procéder pour automatiser mais je suis complètement perdu.

    J'ai bien comprit que je devais mettre des conditions pour tester la valeur de x,y par rapport au premier tracé ( boucle while ) et savoir si c'est un "+" ou un "-". Le décalage entre les différents tracé est donc de 20.

    Voici mes questions:

    Comment automatisé le retour ? ( photo 3 )
    Comment faire pour faire mes conditions et mon algorithme ? J'ai essayer de plusieurs façon différent mais rien ne fonctionne, il faut que le programme choisisse automatique de mettre un -20 ou + 20 suivant le première traçage de la boucle while ?
    Comment faire pour ne pas tracé certaine ligne quand l'écartement entre les ligne est plus petit de 10 ? Voir photo 2

    J'espère que vous avez comprit le fonctionnement et que j'ai été clair dans mes propos.

    Je vous remercie.

  2. #2
    Rédacteur/Modérateur

    Pas simple à comprendre !

    Ton cas serait encore plus complexe avec ce jeu de données :
    165, 125
    165, 285
    365, 285
    365, 365
    525, 365
    525, 285
    625, 285
    625, 165
    525, 165
    525, 125
    185, 125

    Comment ferais-tu dans ce cas pour la partie à droite du dessin ? Quel est le résultat voulu.

    Et ensuite, quelle est ta question précise ?
    Tu veux que chaque courbe soit fermée ?
    Ou bien tu veux un dessin plus ou moins en escargot (=le dernier point du 1er tracé devrait être relié au 1er point du 2ème tracé) ?
    N'oubliez pas le bouton Résolu si vous avez obtenu une réponse à votre question.

  3. #3
    Nouveau membre du Club
    Bonjour,

    Je vais essayer de reformuler:

    Les valeurs dans le fichier.txt correspondent au coordonnées X,Y des points de la ligne.
    Soit, ligne1 = x[i], y[i] - x[i], y[i]
    i = i + 2
    ligne2 = x[i], y[i] - x[i], y[i]
    i = i + 2
    ligne3 = ...

    jusqu'à temps que ma liste soit complète.
    Attention que mon fichier.txt peut contenir 10 cordonnées, comme 30.

    Donc pour savoir à la base le nombre de libre pour mon premier tracer total, je compte les éléments dans ma liste ( liste qui reprend toute les coordonnées de mon fichier.txt)

    Donc dans le code que je propose:

    165, 125
    165, 265
    365, 265
    365, 345
    525, 345
    525, 265
    625, 265
    625, 165
    525, 165
    525, 125
    185, 125

    Soit 22 éléments que je divise en 2 = 11 , -1 et j'ai mon nombre de ligne total, dans ce cas, 10.
    Le but étant de faire des tracés par zone comme sur la photo ci dessous et de faire le reste des tracés à la main ( photo ci dessous, zone 1, zone 2, zone 3 )



    Je voudrais donc que chaque courbe soit fermée comme ci dessous:



    Ma question est:

    Comment créer un algorithme qui va me tracer toute mes lignes automatiques suivant ma boucle while ( première valeur de chaque coordonnée de ma liste récupéré du fichier.txt) avec n'importe quel forme de départ ?



    Que le programme fasse donc la phase de l'escargot seul.

    Je vous remercie

  4. #4
    Membre actif
    Tu connais le jeux du snake ?

    Tu peux faire pareil, en imaginant un serpent qui avance.

  5. #5
    Expert éminent sénior
    Bonjour

    Mouai. On fait comme si le dessin était fait de façon automatique, mais l'aller-retour de l'air chaud rouge, à droite du carré inférieur gauche de l'image, est totalement artistique, unidirectionnel, et non-automatique.

    Avant de vouloir tracer un tel chemin bidirectionnel, il faut déjà prouver son existence.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  6. #6
    Membre actif
    Essaye ça,

    Code Python :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    from tkinter import *
     
    ecart = 20 # Ecart entre les lignes
     
    # Récupération des points ============================================================================================ #
    pts = []; min_x = max_x = min_y = max_y = None
    with open("valeur1.txt", "r") as file:
        for line in file.read().split("\n"):
            xl, yl = map(int, line.split(","))
            pts.append((xl, yl))
     
            min_x = min(xl, min_x or xl); min_y = min(yl, min_y or yl)
            max_x = max(xl, max_x or xl); max_y = max(yl, max_y or yl)
     
    # Construction matrice =============================================================================================== #
    matrix = []
    for i in range(max_y - min_y + 1):
        matrix.append([0 for j in range(max_x - min_x + 1)])
     
    x_scale = lambda x: x - min_x
    y_scale = lambda y: y - min_y
     
    def get_maxtrix(x, y):
        global matrix, min_x, min_y
        return matrix[y_scale(y)][x_scale(x)]
     
    def set_matrix(x, y, value):
        global matrix, min_x, min_y
        matrix[y_scale(y)][x_scale(x)] = value
     
    for i in range(len(pts) - 1):
        x1, y1 = pts[i]
        x2, y2 = pts[i + 1]
     
        for x in range(min(x1, x2), max(x1, x2) + 1):
            for y in range(min(y1, y2), max(y1, y2) + 1):
                set_matrix(x, y, 1)
     
    def display_matrix():
        global matrix
        for i in range(len(matrix)):
            for j in range(len(matrix[i])):
                if matrix[i][j] == 1:
                    print("\033[95m1 ", end = "")
                else:
                    print("\033[0m0 " , end = "")
            print("")
     
    # Calcul des points ================================================================================================== #
    sens, direction = -1, "D" # Données initiales (peut être calculées ...)
    x_c, y_c = pts[-1] # Point courant
     
    rotate_right = {"D": "L", "R": "D", "U": "R", "L": "U"}
    rotate_left  = {"D": "R", "R": "U", "U": "L", "L": "D"}
    ahead = {"D": ("y", +1), "R": ("x", +1), "U": ("y", -1), "L": ("x", -1)}
     
    def can_go_ahead():
        global direction, ahead, x_c, y_c, ecart
        t = ahead[direction]
        if t[0] == "x":
            x_c_new = x_c + t[1]
     
            x_range = (x_c_new + t[1] * (ecart - 1), x_c_new)
            y_range = (y_c - ecart + 1, y_c + ecart - 1)
        else:
            y_c_new = y_c + t[1]
     
            x_range = (x_c - ecart + 1, x_c + ecart - 1)
            y_range = (y_c_new + t[1] * (ecart - 1), y_c_new)
     
        for x in range(min(x_range[0], x_range[1]), max(x_range[0], x_range[1])):
            for y in range(min(y_range[0], y_range[1]), max(y_range[0], y_range[1])):
                if get_maxtrix(x, y) == 1:
                    return False
        return True
     
    def go_ahead():
        global direction, ahead, x_c, y_c
        t = ahead[direction]
        if t[0] == "x": x_c += t[1]
        else: y_c += t[1]
        set_matrix(x_c, y_c, 1)
     
    def can_turn(func_rotate):
        global direction
        c_direction = direction
        direction   = func_rotate[direction]
        can         = can_go_ahead()
        direction   = c_direction
        return can
     
    def turn(func_rotate):
        global direction, x_c, y_c, pts
        pts.append((x_c, y_c)) # On mémorise
        direction = func_rotate[direction]
        go_ahead()
     
    def can_turn_right():
        return can_turn(rotate_right)
     
    def turn_right():
        return turn(rotate_right)
     
    def can_turn_left():
        return can_turn(rotate_left)
     
    def turn_left():
        return turn(rotate_left)
     
    def search_pt():
        global sens
        stop = False
        while not stop:
            if sens == -1:
                if   can_turn_right(): turn_right()
                elif can_go_ahead  (): go_ahead  ()
                elif can_turn_left (): turn_left ()
                else: stop = True
            else:
                if   can_turn_left (): turn_left ()
                elif can_go_ahead  (): go_ahead  ()
                elif can_turn_right(): turn_right()
                else: stop = True
    search_pt()
     
    # Fenêtre ============================================================================================================ #
    w = Tk()
    border = 30
    canvas = Canvas(w, width = (max_x - min_x + 2 * border), height = (max_y - min_y + 2 * border), background = "white")
    canvas.pack(side = LEFT, padx = 5, pady = 5)
    w.resizable(width = False, height = False)
     
    def drawn_line(pt1, pt2):
        global min_x, min_y
        x1 = x_scale(pt1[0]) + border; x2 = x_scale(pt2[0]) + border
        y1 = y_scale(pt1[1]) + border; y2 = y_scale(pt2[1]) + border
        canvas.create_line(x1, y1, x2, y2, fill = "red", width = 1)
     
    for i in range(len(pts) - 1):
        pti, ptj = pts[i], pts[i + 1]
        drawn_line(pti, ptj)
     
    w.mainloop()


    c'est du code un peu bourrin