Source for: lesson5.py [raw]
1class Box():
2
3 def __init__(self, x=0, y=0, w=1, h=1):
4 """Accept arguments to define our box, and store them."""
5 self.x = x
6 self.y = y
7 self.w = w
8 self.h = h
9
10 def __repr__(self):
11 return "Box(%s, %s, %s, %s)" % (self.x, self.y, self.w, self.h)
12
13
14# Many boxes with varying widths
15from random import randint
16
17many_boxes = [Box(w=1 + randint(-5, 5) / 10) for i in range(5000)]
18
19# A few pages all the same size
20pages = [Box(i * 35, 0, 30, 50) for i in range(10)]
21
22# We add a "separation" constant so you can see the boxes individually
23separation = .2
24
25
26def layout(_boxes):
27 # Because we modify the box list, we will work on a copy
28 boxes = _boxes[:]
29 # We start at page 0
30 page = 0
31 # The 1st box should be placed in the correct page
32 previous = boxes.pop(0)
33 previous.x = pages[page].x
34 previous.y = pages[page].y
35 row = []
36 while boxes:
37 # We take the new 1st box
38 box = boxes.pop(0)
39 # And put it next to the other
40 box.x = previous.x + previous.w + separation
41 # At the same vertical location
42 box.y = previous.y
43 # But if it's too far to the right...
44 if (box.x + box.w) > (pages[page].x + pages[page].w):
45 # We adjust the row
46 slack = (pages[page].x + pages[page].w) - (
47 row[-1].x + row[-1].w
48 )
49 bump = slack / len(row)
50 # The 1st box gets 0 bumps, the 2nd gets 1 and so on
51 for i, b in enumerate(row):
52 b.x += bump * i
53 # We start a new row
54 row = []
55 # We go all the way left and a little down
56 box.x = pages[page].x
57 box.y = previous.y + previous.h + separation
58
59 # But if we go too far down
60 if box.y + box.h > pages[page].y + pages[page].h:
61 # We go to the next page
62 page += 1
63 # And put the box at the top-left
64 box.x = pages[page].x
65 box.y = pages[page].y
66
67 # Put the box in the row
68 row.append(box)
69 previous = box
70
71
72layout(many_boxes)
73
74
75import svgwrite
76
77
78def draw_boxes(boxes, fname, size):
79 dwg = svgwrite.Drawing(fname, profile="full", size=size)
80 # Draw the pages
81 for page in pages:
82 dwg.add(
83 dwg.rect(
84 insert=(f"{page.x}cm", f"{page.y}cm"),
85 size=(f"{page.w}cm", f"{page.h}cm"),
86 fill="lightblue",
87 )
88 )
89 # Draw all the boxes
90 for box in boxes:
91 dwg.add(
92 dwg.rect(
93 insert=(f"{box.x}cm", f"{box.y}cm"),
94 size=(f"{box.w}cm", f"{box.h}cm"),
95 fill="red",
96 )
97 )
98 dwg.save()
99
100
101draw_boxes(many_boxes, "lesson5.svg", ("100cm", "50cm"))
102