A program to place words randomly on a canvas. Words are place around a spiral starting from the center. Uses AABB – AABB bounding box collision detection for letter-letter collision.
Ref: Real-time Collision Detection by Christer Ericson
""" May 9, 2019 A program to palce a list of words, randomly on a canvas. Places words around spiral. Uses bounding box collision detection. Author: jithesh Kuyyalil https://jitheshkuyyalil.com Date: April 26, 2019 """ from PIL import Image, ImageDraw, ImageFont import numpy as np from random import randint from spiral import spiral img = Image.new("L", (500, 500)) #word = "b" word_list = ['a', 'b', 'c', 'd', 'e', 'f'] #word_list = 'thebookthiefishere' font_size = 50 font_path = 'DroidSansMono.ttf' draw = ImageDraw.Draw(img) font = ImageFont.truetype(font_path, font_size) # save bounding box co-ordinates [[(), ()], [(), ()]] box_coord =  for word in word_list: # for each letter # x, y, where the word/letter is placed, somewhere top-left sp = spiral(500, 500, 250, 250) count = 0 while True: x, y = next(sp) # font metrics to construct bounding box around letter (x1, y1, x2, y2) = font.getmask(word).getbbox() (width, baseline), (offset_x, offset_y) = font.font.getsize(word) # top left corner rect_1 = (x1 + x + offset_x, y1 + y + offset_y) # bottom right corner. Not clear about -1 # Rectangle fits well with -1. rect_2 = (x2 + x + offset_x -1, y2 + y + offset_y) intersect = False # both letter-boundary, letter-letter collision # boundary collision testing - boundary (0,0), (500,500) # hitting the boundary if not (rect_2 < 500 and rect_2 < 500): intersect = True # only if letter doesn't hit boundary if intersect == False: # checking for collision if box_coord != : #print(box_coord) for box in box_coord: # not intersecting if (rect_1 > box) or (rect_2 < box): continue # intersecting if (rect_1 > box) or (rect_2 < box): continue intersect = True break # interesecting; find new x, y if not intersect : #draw.rectangle([rect_1, rect_2], outline='white') draw.text((x, y), word, fill='white', font=font) # 175, 90 box_coord.append([rect_1, rect_2]) break count = count + 1; if count > 500 * 500: break img.show()
Python code to generate spiral co-ordinates.
""" A program to generate spiral co-ordinates in a 2D square lattice. Algorithm due to Can Berk Güder at stackoverflow.com author: jithesh kuyyalil Date: May 1, 2019 """ def spiral(m, n, Xc = 0, Yc = 0): # 0, 0 at the top left corner # Xc, Yc somewhere on the canvas x = 0 y = 0 dx = 0 dy = -1 for i in range(max(m,n)**2): if (-m/2 < x <= m/2) and (-n/2 < y <= n/2): # from each matrix \ # what is necessary #print(x, y) if Xc != 0 or Yc != 0: yield x + Xc, y + Yc else: yield x, y if x == y or (x < 0 and x == -y) or (x > 0 and x == 1-y): # each turn \ # change dx and dy temp = dx dx = -dy dy = temp #print('dx, dy ', dx, dy) x = x + dx y = y + dy if __name__ == '__main__': import matplotlib.pyplot as plt sp = spiral(300,300, 150, 150) X =  Y =  for i in range(150): #print(next(x)) x, y = next(sp) X.append(x) Y.append(y) plt.plot(X, Y, 'o') plt.show()