mañana

En realidad matplotlib es una mejor opción para dibujar los espirales. ipycanvas tiene un propósito distinto, con ánimo interactivo.

Para imágenes estáticas, matplotlib es mucho más adecuado y poderoso. ipycanvas limitaba el número de polígonos a considerar y también la profundidad de las espirales. El cuaderno claudicaba.

Por ejemplo, con las mismas funciones de ayer, ahora puedo hacer esto:

 
import matplotlib.pyplot as plt

from scipy.spatial import Delaunay

np.random.seed(0)
main_vertices = [[0, 0], [0, 300], [0, 700], [0, 1000], [300, 0], [700, 0], [1000, 0], 
                 [1000, 300], [1000, 700], [1000, 1000], [300, 1000], [700, 1000],
                 [0, 500], [500, 0], [1000, 500], [500, 1000]]
add_ons = ((np.random.normal(size=(1000, 2)) * 150) + 500).tolist() 
all_points = np.array(main_vertices + add_ons)
tri = Delaunay(all_points)

fig, ax = plt.subplots(1, 1, figsize=(17,17), facecolor='#fdf3dc')
_ = ax.axis('off')

for polygon in all_points[tri.simplices]:
    spiral_list = np.array(spiral(polygon.tolist(), N=5000, fraction=0.1))
    plt.plot(spiral_list[:, 0], spiral_list[:, 1], linewidth=0.1, color='black')

Esta triangulación de Delaunay está basada en mil puntos de ruido normal y cada triángulo espiral tiene una profundidad de 5000 trazos. Se ve así:

espirales

El código para generarla con matplotlib, como notarán, es muy sencillo, y aguanta muchísima más carga que ipycanvas.

Después de eso jugué a romper polígonos al azar:

from scipy.spatial import Voronoi

def shuffle_polygon(polygon):
    # This is ugly because np.random.choice does not like multidimensional arrays.
    return (
        np.array(polygon)
        [np.random.choice(
            list(range(len(polygon))),
            size=len(polygon),
            replace=False)]
        .tolist()
    )

np.random.seed(17)
all_points = ((np.random.normal(size=(1000, 2)) * 150) + 500).tolist() 
vor = Voronoi(all_points)
voronoi_polygons = [[vor.vertices[z].tolist() for z in x] 
                    for x in vor.regions
                    if x and all([y>=0 for y in x])]
voronoi_polygons = [x for x in voronoi_polygons 
                    if (np.array(x) > 0).all() 
                    and (np.array(x) < 1000).all()]

fig, ax = plt.subplots(1, 1, figsize=(17,17), facecolor='#fdf3dc')
_ = ax.axis('off')

for polygon in voronoi_polygons:
    spiral_list = np.array(spiral(shuffle_polygon(polygon), N=5000, fraction=0.1))
    plt.plot(spiral_list[:, 0], spiral_list[:, 1], linewidth=0.1, color='black')

espirales