Está en la página 1de 8

Diagramas de Voronoi

Materia: Big Data para Redes Sociales


Dra. Claudia Guadalupe Gómez Santillán
Alumno: Kevin Cantú Gómez
Los polígonos de Thiessen, nombrados en honor al meteorólogo estadounidense Alfred H.
Thiessen, son una construcción geométrica que permite construir una partición del plano
euclídeo. Estos objetos también fueron estudiados por el matemático ruso Gueorgui
Voronói en 1907, de donde toman el nombre alternativo de Diagramas de
Voronoi o Teselación de Voronoi.
Los Diagramas de Voronoi son uno de los métodos de interpolación más simples, basados
en la distancia euclidiana. Se crean al unir los puntos entre sí, trazando las mediatrices de
los segmentos de unión. Las intersecciones de estas mediatrices determinan una serie
de polígonos en un espacio bidimensional alrededor de un conjunto de puntos de control, de
manera que el perímetro de los polígonos generados sea equidistante a los puntos vecinos y
designan su área de influencia.

20 puntos en el plano y su partición del plano en regiones de voronoi.

Definición formal
Construcción de la región de Voronói de un sitio debido a la intersección de semiplanos.

Aplicaciones
Esta estructura sirve para diferenciar el espacio en regiones puede aplicarse al futbol, al
diagnostico de tumores o para evitar las colisiones de barcos en la costa.
Por ejemplo, en el futbol.
Si pensamos en los jugadores sobre el terreno de juego como puntos sobre un plano,
podemos asignarle a cada uno de ellos su región de Voronoi que estará formada por los
puntos del terreno de juego que están mas cerca de cada jugador que del resto.
Evidentemente, como los jugadores no están quietos, en general, este diagrama ira
modificándose con el tiempo, pero nos puede decir, en cada instante, que equipo esta mejor
posicionado en el campo.
Otro tipo de aplicaciones que igual no se nos ocurren en primera instancia tiene que ver
con las fronteras de las regiones. Imaginen que en lugar de querer encontrar la
farmacia más cercana a ustedes quieren cruzar la ciudad pasando lo más lejos posible
de cualquier farmacia. Igual no lo ven con farmacias, pero pueden pensar en pastelerías
y/o heladerías si están en eso que llaman la operación bikini. En ese caso, la ruta a
seguir nos la dan las líneas de las fronteras del diagrama de Voronoi. Caminando sobre
dichas líneas estaremos siempre lo más alejados posible de las dos pastelerías que
comparten esa línea en su frontera de Voronoi. Esto se utiliza para, por ejemplo, evitar
colisiones de barcos al atravesar zonas escarpadas de la costa.

Diagramas de Voronoi en Python y R


Tomamos de un espacio bidimensional una zona con medidas conocidas que
contiene k puntos semilla pi, representados por sus coordenadas (xi,yi). Lo que se busca es
dividir esa zona en regiones llamadas celdas de Voronoi de tal forma que todos los puntos que
pertenecen a la región de pi estén más cerca de esa semilla que a cualquier otra.
El modelo matemático en sí es continuo, es decir, las coordenadas son números reales, pero
nosotros lo vamos a discretizar en esta práctica. Vamos a representar la zona por una
matriz n×n y las coordenadas serán entonces números enteros en [1,n]. Por el momento,
vamos a colocar uniformemente al azar las k semillas, representadas por los
números 1 a k dentro de la matriz, procurando que ocupen una posición distinta dentro de la
matríz cada una de las semillas. También vamos a visualizar cómo se ve la zona con las
semillas puestas.
Diagrama de voronoi en Python

Diagrama de voronoi en R
Python
import seaborn as sns
from random import randint
from PIL import Image, ImageColor
 
n = 40
k = 12
semillas = []
for s in range(k):
    while True:
        x = randint(0, n - 1)
        y = randint(0, n - 1)
        if (x, y) not in semillas:
            semillas.append((x, y))
            break
 
from math import sqrt
def celda(pos):
    y = pos // n
    x = pos % n
    if pos in semillas:
        return semillas.index(pos)
    cercano = None
    menor = n * sqrt(2)
    for i in range(k):
        (xs, ys) = semillas[i]
        dx = x - xs
        dy = y - ys
        dist = sqrt(dx**2 + dy**2)
        if dist < menor:
            cercano = i
            menor = dist
    return cercano
 
import multiprocessing
if __name__ == "__main__":
    celdas = None
    with multiprocessing.Pool() as pool:
        celdas = pool.map(celda, range(n * n))
        zona = Image.new('RGB', (n, n))
        p = zona.load()
        c = sns.color_palette("Set3", k).as_hex()
        for i in range(n * n):
            s = celdas.pop(0)
            p[i % n, i // n] = ImageColor.getrgb(c[s])
    visual = zona.resize((10 * n,  10 * n))
    visual.show()
    visual.save("p4pc.png")

R
n <-  40
zona <- matrix(rep(0, n * n), nrow = n, ncol = n)
k <- 12
x <- rep(0, k) # ocupamos almacenar las coordenadas x de las semillas
y <- rep(0, k) # igual como las coordenadas y de las semillas
 
for (semilla in 1:k) {
    while (TRUE) { # hasta que hallamos una posicion vacia para la
semilla
        fila <- sample(1:n, 1)
        columna <- sample(1:n, 1)
        if (zona[fila, columna] == 0) {
            zona[fila, columna] = semilla
            x[semilla] <- columna
            y[semilla] <- fila
            break
        }
    }
}
 
celda <-  function(pos) {
    fila <- floor((pos - 1) / n) + 1
    columna <- ((pos - 1) %% n) + 1
    if (zona[fila, columna] > 0) { # es una semilla
        return(zona[fila, columna])
    } else {
        cercano <- NULL # sin valor por el momento
        menor <- n * sqrt(2) # mayor posible para comenzar la busqueda
        for (semilla in 1:k) {
            dx <- columna - x[semilla]
            dy <- fila - y[semilla]
            dist <- sqrt(dx^2 + dy^2)
            if (dist < menor) {
                cercano <- semilla
                menor <- dist
            }
        }
        return(cercano)
    }
}
suppressMessages(library(doParallel))
registerDoParallel(makeCluster(detectCores() - 1))
celdas <- foreach(p = 1:(n * n), .combine=c) %dopar% celda(p)
stopImplicitCluster()
voronoi <- matrix(celdas, nrow = n, ncol = n, byrow=TRUE)
rotate <- function(x) t(apply(x, 2, rev))
png("p4s.png")
par(mar = c(0,0,0,0))
image(rotate(zona), col=rainbow(k+1), xaxt='n', yaxt='n')
graphics.off()
png("p4c.png")
par(mar = c(0,0,0,0))
image(rotate(voronoi), col=rainbow(k+1), xaxt='n', yaxt='n')
graphics.off()

Diagramas de Voronoi
Python R

Celdas de Voronoi con dos puntos

Celdas de Voronoi con doce puntos


Celdas de Voronoi con mil puntos

También podría gustarte