Norm Sign Generator (rewrite) II

Norm Sign Generator Installation

Norm Sign Generator Software

Define lines instead of points

Instead of working with single points (as in the previous notebook), we’ll create a list of all allowed lines.

grid 3x3

Imports

from flat import document, shape, rgb
from IPython.display import SVG, display
import numpy as np
import random
import itertools
from matplotlib import pyplot as plt

Functions

def show(page):
    display(SVG(page.svg()))
    
def draw_grid(page, x, y, width, height, color=rgb(200, 200, 200)):
    for elem in list(x):
        line = shape().stroke(color).line(elem, 0, elem, height)
        page.place(line)
    for elem in list(y):
        line = shape().stroke(color).line(0, elem, width, elem)
        page.place(line)

Elements

lines = [(0, 0, 0.5, 0), # outer lines, starting with top left, then clockwise
         (0.5, 0, 1, 0),
         (1, 0, 1, 0.5),
         (1, 0.5, 1, 1),
         (1, 1, 0.5, 1),
         (0.5, 1, 0, 1),
         (0, 1, 0, 0.5),
         (0, 0.5, 0, 0),
         (0, 0, 0.5, 0.5), # diagonal lines to center, top left, then clockwise cells
         (1, 0, 0.5, 0.5),
         (1, 1, 0.5, 0.5),
         (0, 1, 0.5, 0.5),
         (0, 0.5, 0.5, 0), # diagnoal lines between outer lines, top left, then clockwise
         (0.5, 0, 1, 0.5),
         (1, 0.5, 0.5, 1),
         (0.5, 1, 0, 0.5),
         (0.5, 0, 0.5, 0.5), # inner cross
         (1, 0.5, 0.5, 0.5),
         (0.5, 1, 0.5, 0.5),
         (0, 0.5, 0.5, 0.5)]

Next we’ll test how to transform a list of values into a numpy array. This makes it easy to perform mathematical operations on vectors (n-dimensional lists of numbers).

print('Line before its transformation:', lines[2])

x = np.asarray(lines[2]) * 10 # multiply each item with the same value
print('Line after its transformation:', x)

# Unpacking the array into individual variables
x0, y0, x1, y1 = x
print('x0:', x0)
print('y0:', y0)
print('x1:', x1)
print('y1:', y1)
Line before its transformation: (1, 0, 1, 0.5)
Line after its transformation: [10.  0. 10.  5.]
x0: 10.0
y0: 0.0
x1: 10.0
y1: 5.0

Draw all possible lines in one grid

size = 300
margin = 10

width = size + 2*margin
height = size + 2*margin

d = document(width, height, 'pt')
p = d.addpage()

draw_grid(p, np.linspace(0+margin, size+margin, 3).astype(int), np.linspace(0+margin, size+margin, 3).astype(int), width, height) 

s = shape().stroke(rgb(0, 0, 0))

for line in lines:
    x0, y0, x1, y1 = np.asarray(line) * size + margin # multiply each point with size + add the margin
    r, g, b = [random.randint(0, 255) for x in range(3)]
    line = shape().stroke(rgb(r, g, b)).width(3).cap('round').line(x0, y0, x1, y1)
    p.place(line)

show(p)
_images/norm_sign_generator_2_11_0.svg
size = 300
margin = 10

width = size + 2*margin
height = size + 2*margin

d = document(width, height, 'pt')
p = d.addpage()

s = shape().stroke(rgb(0, 0, 0))

draw_grid(p, np.linspace(0+margin, size+margin, 3).astype(int), np.linspace(0+margin, size+margin, 3).astype(int), width, height) 

for i in range(7):
    # pick a random line
    line = random.choice(lines)
    x0, y0, x1, y1 = np.asarray(line) * size + margin # multiply each point with size + add the margin
    line = shape().stroke(rgb(0, 0, 0)).width(3).cap('round').line(x0, y0, x1, y1)
    p.place(line)

show(p)
_images/norm_sign_generator_2_12_0.svg

Get possible combinations

Next we’ll use pythons itertools to compute all combinations of our lines.

See for example https://docs.python.org/3/library/itertools.html#itertools.combinations and https://datagy.io/python-combinations-of-a-list/ or press ctrl+i with the cursor on the function.

Test with sample data

# import itertools

elements = ['ab', 'bc', 'ca']

combinations = list(itertools.combinations(elements, r=2))

print(combinations)
[('ab', 'bc'), ('ab', 'ca'), ('bc', 'ca')]

All shapes with 2 lines

combinations = list(itertools.combinations(lines, r=2))

print('length:', len(combinations))
for c in combinations[:5]:
    print(c)
length: 190
((0, 0, 0.5, 0), (0.5, 0, 1, 0))
((0, 0, 0.5, 0), (1, 0, 1, 0.5))
((0, 0, 0.5, 0), (1, 0.5, 1, 1))
((0, 0, 0.5, 0), (1, 1, 0.5, 1))
((0, 0, 0.5, 0), (0.5, 1, 0, 1))

Place all possibilities

size = 200
margin = 20

width = size + 2*margin
height = size + 2*margin
       
d = document(width, height, 'mm')


s = shape().stroke(rgb(0, 0, 0))


for combination in combinations:
    
    p = d.addpage()
    draw_grid(p, np.linspace(0+margin, size+margin, 3).astype(int), np.linspace(0+margin, size+margin, 3).astype(int), width, height) 
    
    # Iterate over elements of that list
    for line in combination:
        x0, y0, x1, y1 = np.asarray(line) * size + margin # multiply each point with size + add the margin
        line = shape().stroke(rgb(0, 0, 0)).width(3).cap('round').line(x0, y0, x1, y1)
        p.place(line)
        

# Save pdf
d.pdf('data/sign_generator_r2.pdf')

# Display the last page
show(p)
_images/norm_sign_generator_2_19_0.svg

Appendix

Distribution of combinations

x = []
y = []

for i in range(2, len(lines)+1):
    
    # Store the number of lines on the x-axis
    x.append(i)
    
    # Store the amount of combinations on the y-axis
    it = itertools.combinations(lines, r=i)
    combinations = list(it)
    y.append(len(combinations))
plt.scatter(x, y)
plt.show()
_images/norm_sign_generator_2_23_0.png