Flat - Export

In this notebook we’ll save the generated forms as svg, png and pdf. The shapes are generated with the code from the chapter “Flat - Path Permutations”.

Imports

from flat import document, shape, rgb, rgba
from bezmerizing import Path, Polyline
from IPython.display import SVG, display
import numpy as np
import random
import itertools
from sympy.utilities.iterables import multiset_permutations
import os

Functions

This section defines functions that will be used later.

# Display a flat page here in the notebook
def show(page):
    display(SVG(page.svg()))
       
# Draw a grid of horizontal and vertical lines based on 
# given coordinates
def draw_grid(page, x_coords, y_coords, color=rgb(200, 200, 200)):
    
    # Get minimum and maximum values 
    min_x, max_x = min(x_coords), max(x_coords)
    min_y, max_y = min(y_coords), max(y_coords)
    
    # Draw vertical lines
    for x in list(x_coords):
        line = shape().stroke(color).line(x, min_y, x, max_y)
        page.place(line)

    # Draw horizontal lines
    for y in list(y_coords):
        line = shape().stroke(color).line(min_x, y, max_x, y)
        page.place(line)

# Translate a list of points into a list of coordinates
def indices_to_coordinates(list_of_indices, coordinates):
    c = []
    for index in list_of_indices:
        x = coordinates[0][index[0]]
        y = coordinates[1][index[1]]
        c.append([x, y])
        
    return c

Flat Document

The following code defines the general setup of the document. It has width and height and a margin. The size of the grid is calculated as the size of the document minus the margin on all sides of the document.

# Width and height of the document
width, height = 400, 400

# Margin between border of the document and
# border of the grid
margin = 10

# Size of the grid
grid_width = width - 2*margin
grid_height = height - 2*margin

# Create the document
d = document(width, height, 'pt')

Grid Definition

The grid is defined through the number of points on the x and y axis. In the next step the coordinates for each point are calculated. This is done with the linspace() function from Numpy (np). It distributes the points on a given range, in this case the size of the grid. It also takes the margin into account.

# Number of points per row 
# (number of cells = row -1)
grid_x = 6
grid_y = 6

# Create coordinates
coords_x = np.linspace(margin, margin+grid_width, grid_x)
coords_y = np.linspace(margin, margin+grid_height, grid_y)

print(coords_x)
print(coords_y)
[ 10.  86. 162. 238. 314. 390.]
[ 10.  86. 162. 238. 314. 390.]

Calculate permutations

The start and end point will be fixed and the order of the points in-between will be permutated.

points = [[0, 2], [0, 2], [1, 1], [2, 4], [3, 2], [4, 2], [5, 3], [5, 3]]
print('points:', points)

# Reduce the list to the mid-points
variable_points = points[2:-2]
print('variable_points:', variable_points)

permutations = list(multiset_permutations(variable_points))
# Add start and end points

permutations = [points[:2] + perm + points[-2:] for perm in permutations]

for p in permutations:
    print(p)
points: [[0, 2], [0, 2], [1, 1], [2, 4], [3, 2], [4, 2], [5, 3], [5, 3]]
variable_points: [[1, 1], [2, 4], [3, 2], [4, 2]]
[[0, 2], [0, 2], [1, 1], [2, 4], [3, 2], [4, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [1, 1], [2, 4], [4, 2], [3, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [1, 1], [3, 2], [2, 4], [4, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [1, 1], [3, 2], [4, 2], [2, 4], [5, 3], [5, 3]]
[[0, 2], [0, 2], [1, 1], [4, 2], [2, 4], [3, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [1, 1], [4, 2], [3, 2], [2, 4], [5, 3], [5, 3]]
[[0, 2], [0, 2], [2, 4], [1, 1], [3, 2], [4, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [2, 4], [1, 1], [4, 2], [3, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [2, 4], [3, 2], [1, 1], [4, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [2, 4], [3, 2], [4, 2], [1, 1], [5, 3], [5, 3]]
[[0, 2], [0, 2], [2, 4], [4, 2], [1, 1], [3, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [2, 4], [4, 2], [3, 2], [1, 1], [5, 3], [5, 3]]
[[0, 2], [0, 2], [3, 2], [1, 1], [2, 4], [4, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [3, 2], [1, 1], [4, 2], [2, 4], [5, 3], [5, 3]]
[[0, 2], [0, 2], [3, 2], [2, 4], [1, 1], [4, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [3, 2], [2, 4], [4, 2], [1, 1], [5, 3], [5, 3]]
[[0, 2], [0, 2], [3, 2], [4, 2], [1, 1], [2, 4], [5, 3], [5, 3]]
[[0, 2], [0, 2], [3, 2], [4, 2], [2, 4], [1, 1], [5, 3], [5, 3]]
[[0, 2], [0, 2], [4, 2], [1, 1], [2, 4], [3, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [4, 2], [1, 1], [3, 2], [2, 4], [5, 3], [5, 3]]
[[0, 2], [0, 2], [4, 2], [2, 4], [1, 1], [3, 2], [5, 3], [5, 3]]
[[0, 2], [0, 2], [4, 2], [2, 4], [3, 2], [1, 1], [5, 3], [5, 3]]
[[0, 2], [0, 2], [4, 2], [3, 2], [1, 1], [2, 4], [5, 3], [5, 3]]
[[0, 2], [0, 2], [4, 2], [3, 2], [2, 4], [1, 1], [5, 3], [5, 3]]

Export

Flat can export the whole document as a pdf, like

# Create the document
d = document(width, height, 'pt')

# Add some content

# Export pdf
d.pdf('filename.pdf')

Furthermore, it can export single pages as png or svg:

# Create the document
d = document(width, height, 'pt')

# Add a page
page = d.addpage()

# Add some content

# Export the page as svg
page.svg('filename.svg')

# Export the page as png
page.png('filename.png')

We’ll insert this at the end of the for-loop and outside of the for-loop below.

Loop over permutations and store them as svg

# We'll use enumerate() to get an index 
# that will be used for the file name
for index, p in enumerate(permutations):


    # Add a page to the document
    page = d.addpage()

    # Call the function to draw a grid
    # As input it takes the list of coordinates defined above
    draw_grid(page, coords_x, coords_y)

    # Draw a path betweeen points
    # For catmull-rom the first and last points have to be duplicated
    # (or replaced by close values)
    points = p
    # Translate the points into coordinates
    coords = indices_to_coordinates(points, [coords_x, coords_y])
    # Feed the coordinates into the Polyline object
    pline = Polyline(coords)

    # Transform the Polyline from above into a spline
    spline = pline.catmull_spline(tightness=0.1)
    # Transform it into a path
    path = spline.to_path()

    # Feed the path into flat's path function
    fig = shape().stroke(rgb(0, 0, 0)).nofill().width(1)
    page.place(fig.path(path))

    # Feed the page into the show() function to display it inside the notebook
    show(page)
    
    # Save the page as svg
    # create a directory (or recursive directories) if it does not exist yet
    os.makedirs('export', exist_ok=True)
    page.svg(f'export/path_permutation_{index:03}.svg')
    
# Export the whole document as pdf
d.pdf('export/path_permutations.pdf')

# Sometimes it's good to use a timestamp for an individual filename
# For example if it's not possible to use a counter like the index above
from datetime import datetime
d.pdf('export/path_permutations_' + str(int(datetime.timestamp(datetime.now()))) + '.pdf')

# Empty print statement to avoid the pdf output in the notebook
print()
_images/flat_07_export_13_0.svg_images/flat_07_export_13_1.svg_images/flat_07_export_13_2.svg_images/flat_07_export_13_3.svg_images/flat_07_export_13_4.svg_images/flat_07_export_13_5.svg_images/flat_07_export_13_6.svg_images/flat_07_export_13_7.svg_images/flat_07_export_13_8.svg_images/flat_07_export_13_9.svg_images/flat_07_export_13_10.svg_images/flat_07_export_13_11.svg_images/flat_07_export_13_12.svg_images/flat_07_export_13_13.svg_images/flat_07_export_13_14.svg_images/flat_07_export_13_15.svg_images/flat_07_export_13_16.svg_images/flat_07_export_13_17.svg_images/flat_07_export_13_18.svg_images/flat_07_export_13_19.svg_images/flat_07_export_13_20.svg_images/flat_07_export_13_21.svg_images/flat_07_export_13_22.svg_images/flat_07_export_13_23.svg