BOXES v0.4

In the previous lesson we totally nailed drawing inside the lines ... horizontally. Let's improve on that by being bidimensional.

The code for the Box class has not changed, so it's not shown.

But now, instead of a big box, let's have a list of, say, 10 pages (or large boxes), one below the other, slightly separated.

16pages = [Box(0, i * 55, 30, 50) for i in range(10)]

Of course our layout routine needs improvements to handle overflowing a page vertically.

18# We add a "separation" constant so you can see the boxes individually
19separation = .2
20
21
22def layout(_boxes):
23    # Because we modify the box list, we will work on a copy
24    boxes = _boxes[:]
25    # We start at page 0
26    page = 0
27    # The 1st box should be placed in the correct page
28    previous = boxes.pop(0)
29    previous.x = pages[page].x
30    previous.y = pages[page].y
31    while boxes:
32        # We take the new 1st box
33        box = boxes.pop(0)
34        # And put it next to the other
35        box.x = previous.x + previous.w + separation
36        # At the same vertical location
37        box.y = previous.y
38        # But if it's too far to the right...
39        if (box.x + box.w) > (pages[page].x + pages[page].w):
40            # We go all the way left and a little down
41            box.x = pages[page].x
42            box.y = previous.y + previous.h + separation
43
44        # But if we go too far down
45        if box.y + box.h > pages[page].y + pages[page].h:
46            # We go to the next page
47            page += 1
48            # And put the box at the top-left
49            box.x = pages[page].x
50            box.y = pages[page].y
51
52        previous = box
53
54
55layout(many_boxes)

We need to change our drawing code to draw more than one page.

57import svgwrite
58
59
60def draw_boxes(boxes, fname, size):
61    dwg = svgwrite.Drawing(fname, profile="full", size=size)
62    # Draw the pages
63    for page in pages:
64        dwg.add(
65            dwg.rect(
66                insert=(f"{page.x}cm", f"{page.y}cm"),
67                size=(f"{page.w}cm", f"{page.h}cm"),
68                fill="lightblue",
69            )
70        )
71    # Draw all the boxes
72    for box in boxes:
73        dwg.add(
74            dwg.rect(
75                insert=(f"{box.x}cm", f"{box.y}cm"),
76                size=(f"{box.w}cm", f"{box.h}cm"),
77                fill="red",
78            )
79        )
80    dwg.save()
81
82
83draw_boxes(many_boxes, "lesson4.svg", ("100cm", "100cm"))

And here is the output:

lesson4.svg

Would this work if the pages are arranged differently? Let's put the pages side by side instead.

85pages = [Box(i * 35, 0, 30, 50) for i in range(10)]
86layout(many_boxes)
87draw_boxes(many_boxes, "lesson4_side_by_side.svg", ("100cm", "50cm"))

lesson4_side_by_side.svg

And how about pages of different sizes?

90from random import randint
91
92pages = [
93    Box(i * 35, 0, 30 - randint(0, 10), 50 - randint(0, 30))
94    for i in range(10)
95]
96layout(many_boxes)
97draw_boxes(many_boxes, "lesson4_random_sizes.svg", ("100cm", "50cm"))

lesson4_random_sizes.svg

So, we can fill pages and pages with little red squares now. Nice!

How about we make the squares not be all the same width?

99many_boxes = [Box(w=1 + randint(-5, 5) / 10) for i in range(5000)]
100layout(many_boxes)
101draw_boxes(
102    many_boxes, "lesson4_random_box_sizes.svg", ("100cm", "50cm")
103)

This adds "noise" to the width of the boxes, so they are now anything between 0.5 and 1.5 units wide.

lesson4_random_box_sizes.svg

That looks interesting...


Further references:

results matching ""

    No results matching ""