Aller au contenu

Visualisation des cellules de Voronoï

Représentation graphique en python

On donne ci-dessous quelques éléments de code python pour représenter des points dans un repère.

On utilise pour cela la bibliothèque matplotlib.

Exemple 1

# import de la bibliothèque pour nos figures
import matplotlib.pyplot as plt 

# dessin d'un point de coordonnées (2,3),
# représenté par un carré ( 's' pour square)
# de couleur noir (k)
# de taille 10
plt.plot(2,3, marker='s', color='k', markersize=10)

# pour lancer la construction de la figure à l'écran
plt.show()
Liste des formes et couleurs

Vous trouverez la liste des markers (forme des points) ici ou .
Et la liste des couleurs ici ou .

Image obtenue

On obtient:

A vous.

Modifier forme, couleur, taille et position du point pour bien comprendre le fonctionnement.

Exemple 2

On représente maintenant une série de points.

Pour cela, on crée la liste X des abscisses de ces points et la liste Y des ordonnées de ces points.
Les points placés ci-dessous sont donc les points (0,0), (1,1), (2,4), (3,9) et (4,16).

import matplotlib.pyplot as plt

X = [0, 1, 2, 3, 4]
Y = [0, 1, 4, 9, 16]

# points de couleur cyan (c), de forme hexagonale (h)
# on ne relie pas les points (linestyle = '')
plt.plot(X,Y, marker='h', color='c', markersize=20, linestyle='')
plt.show()
Valeurs de linestyle

Les valeurs pour linestyle (ou ls en abrégé):

  • ‘solid’
  • ‘dashed’
  • ‘dashdot’
  • ‘dotted’
  • '-'
  • '--'
  • '-.'
  • ':'
  • 'None'
  • ' '
  • '' (chaîne vide)
Image obtenue

On obtient:

A vous.

Modifier forme, couleur, taille, liste des points et linestyle pour bien comprendre le fonctionnement.

Exercice 1

Compléter le script ci-dessous en écrivant un corps possible pour la fonction representation dont la spécification est donnée en docstring.

from random import randint
from math import sqrt, inf
import matplotlib.pyplot as plt

xmin, xmax = -20, 20
ymin, ymax = -20, 20


def genereListePoints(nbmin, nbmax):
    """
    nbmin -- entier
    nbmax -- entier
    précondition: nbmin < nbmax

    Renvoie une liste de couples d'entiers, le premier élément du couple
    est compris entre xmin et xmax (au sens large), le second élément entre 
    ymin et ymax (au sens large).
    Les couples (x, y) sont générés au hasard.
    Le nombre de couples est généré au hasard, entre nbmin et nbmax.
    """
    assert nbmin < nbmax, "Attention, on doit avoir nbmin < nbmax"
    nbPoints = randint(nbmin, nbmax)
    return [(randint(xmin, xmax), randint(ymin, ymax)) for _ in range(nbPoints)]

def distance(x,y,a,b):
    """
    Renvoie la distance euclidienne entre A(a,b) et M(x,y)
    """
    dx, dy = x-a, y-b
    return sqrt(dx**2 + dy**2)



def plusProcheVoisin(listePoints, x, y):
    """
    listePoints -- liste de points à coordonnées entières 
    x -- entier entre xmin et xmax
    y -- entier entre ymin et ymax

    Renvoie le point de la liste listePoints le plus proche de (x,y)
    """
    distance_min = inf # initialisation à +infini
    for point in listePoints:
        d = distance(x, y, point[0], point[1])
        if d < distance_min:
            distance_min = d
            pointPlusProche = point
    return pointPlusProche


def representation(nvPoint, listePoints):
    """
    nvPoint -- couple (x,y) des coordonnées d'un point, 
    précondition:  xmin <= x <= xmax, ymin <= y <=  ymax
    listePoints -- liste de points à coordonnées dans [xmin, xmax]*[ymin,ymax]

    Affiche nvPoint en rouge forme carrée.
    Affiche les points de listePoints en bleu, forme ronde.
    Affiche le point de listePoints le plus proche de nvPoint avec un diamètre plus grand.
    """

    ## CORPS A DEFINIR ##


points = genereListePoints(8, 20)
point = (2,3)
representation(point, points) 
Un code possible
from random import randint
from math import sqrt, inf
import matplotlib.pyplot as plt

xmin, xmax = -20, 20
ymin, ymax = -20, 20


def genereListePoints(nbmin, nbmax):
    """
    nbmin -- entier
    nbmax -- entier
    précondition: nbmin < nbmax

    Renvoie une liste de couples d'entiers, le premier élément du couple
    est compris entre xmin et xmax (au sens large), le second élément entre 
    ymin et ymax (au sens large).
    Les couples (x, y) sont générés au hasard.
    Le nombre de couples est généré au hasard, entre nbmin et nbmax.
    """
    assert nbmin < nbmax, "Attention, on doit avoir nbmin < nbmax"
    nbPoints = randint(nbmin, nbmax)
    return [(randint(xmin, xmax), randint(ymin, ymax)) for _ in range(nbPoints)]

def distance(x,y,a,b):
    """
    Renvoie la distance euclidienne entre A(a,b) et M(x,y)
    """
    dx, dy = x-a, y-b
    return sqrt(dx**2 + dy**2)



def plusProcheVoisin(listePoints, x, y):
    """
    listePoints -- liste de points à coordonnées entières 
    x -- entier entre xmin et xmax
    y -- entier entre ymin et ymax

    Renvoie le point de la liste listePoints le plus proche de (x,y)
    """
    distance_min = inf # initialisation à +infini
    for point in listePoints:
        d = distance(x, y, point[0], point[1])
        if d < distance_min:
            distance_min = d
            pointPlusProche = point
    return pointPlusProche


def representation(nvPoint, listePoints):
    """
    nvPoint -- couple (x,y) des coordonnées d'un point, xmin <= x <= xmax, ymin <= y <=  ymax
    listePoints -- liste de points à coordonnées dans [xmin, xmax]*[ymin,ymax]

    Affiche nvPoint en rouge forme carrée.
    Affiche les points de listePoints en bleu, forme ronde.
    Affiche le point de listePoints le plus proche de nvPoint avec un diamètre plus grand.
    """
    lePlusProche = plusProcheVoisin(listePoints, nvPoint[0], nvPoint[1])
    #liste des abscisses
    X = [point[0] for point in listePoints]
    #liste des ordonnées
    Y = [point[1] for point in listePoints] 
    plt.plot(X,Y, marker='o', color='b', markersize=4, linestyle='')
    plt.plot(nvPoint[0],nvPoint[1], marker='s', color='r', markersize=6)
    plt.plot(lePlusProche[0],lePlusProche[1], marker='o', color='b', markersize=10)
    plt.show()


points = genereListePoints(8, 20)
point = (2,3)
representation(point, points) 

Exemple de graphique obtenu:

Dessiner les cellules de Voronoi

À partir des scripts précédents, on peut définir une fonction qui nous permettra de visualiser les différentes cellules de Voronoï.

Étudier et tester le script suivant:

from random import randint, random
from math import sqrt, inf
import matplotlib.pyplot as plt

xmin, xmax = -20, 20
ymin, ymax = -20, 20


def genereListePoints(nbmin, nbmax):
    """
    nbmin -- entier
    nbmax -- entier
    précondition: nbmin < nbmax

    Renvoie une liste de couples d'entiers, le premier élément du couple
    est compris entre xmin et xmax (au sens large), 
    le second élément entre 
    ymin et ymax (au sens large).
    Les couples (x, y) sont générés au hasard.
    Le nombre de couples est généré au hasard, entre nbmin et nbmax.
    """
    nbPoints = randint(nbmin, nbmax)
    return [(randint(xmin, xmax), randint(ymin, ymax)) for _ in range(nbPoints)]




def distance(x,y,a,b):
    """
    Renvoie la distance euclidienne entre A(a,b) et M(x,y)
    """
    dx, dy = x-a, y-b
    return sqrt(dx**2 + dy**2)





def indicePlusProcheVoisin(listePoints, x, y):
    """
    listePoints -- liste de points à coordonnées entières 
    x -- entier entre xmin et xmax
    y -- entier entre ymin et ymax

    Renvoie l'indice du point de la liste listePoints le plus proche de (x,y)
    """
    distance_min = inf # initialisation à +infini

    for indice, point in enumerate(listePoints):
        d = distance(x, y, point[0], point[1])
        if d < distance_min:
            distance_min = d
            pointPlusProche = point
            indiceDuMin = indice
    return indiceDuMin





def couleurAuHasard():
    """
    renvoie une couleur au hasard
    On pourra l'utiliser ainsi: plt.plot(..., color = couleurAuHasard(),...) 
    Voir
    https://matplotlib.org/3.1.0/gallery/color/color_demo.html#sphx-glr-gallery-color-color-demo-py
    """
    return (random(), random(), random())


def coloreCellules(listePoints):
    """
    listePoints -- liste de points dans [xmin,xmax]*[ymin,ymax] 
    (abris à rejoindre).

    Colore par une couleur au hasard chaque cellule de Voronoi définie par listePoints
    dans [xmin,xmax]*[ymin,ymax],
    c'est à dire colore la "zone de proximité" d'un abri.
    """

    # couleurs: liste de couleurs 
    # couleurs[0] sera la couleur de la zone de proximité
    # de l'abri listePoints[0]
    # couleurs[1] sera la couleur de la zone de proximité
    # de l'abri listePoints[1], etc...
    couleurs = [couleurAuHasard() for _ in range(len(listePoints))]


    # on parcourt le plan (en se limitant aux points à coord entières)
    # et on colore chaque point par la couleur correspondant 
    # à l'abri le plus proche
    for x in range(xmin, xmax+1):
        for y in range(ymin, ymax+1):
            indiceAbriPlusProche = indicePlusProcheVoisin(listePoints, x, y)
            plt.plot(x,y, marker='.', color= couleurs[indiceAbriPlusProche])

    # on dessine en noir les abris
    X = [point[0] for point in listePoints]
    Y = [point[1] for point in listePoints] 
    plt.plot(X,Y, marker='s', color='k', markersize=8, linestyle='')
    plt.show()


points = genereListePoints(8, 20)
coloreCellules(points)

Exemple de résultat: