-
Notifications
You must be signed in to change notification settings - Fork 5
Open
Description
Thanks for this nice port to python, here there is a version of your code ported to numpy and using matplotlib for plotting
#!/usr/bin/python3
import numpy as np
from time import time
import matplotlib.pyplot as plt
PI = np.pi
# increase this number for larger tilings.
N_ITERATIONS = 4
IDENTITY = np.array([[1,0,0],
[0,1,0]], 'float32')
TILE_NAMES = ["Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Phi", "Psi"]
COLOR_MAP = {"Gamma": np.array((211, 95, 95),'f')/255.,
"Gamma1": np.array((200, 55, 55),'f')/255.,
"Gamma2": np.array((222, 135, 135),'f')/255.,
"Delta": np.array(( 0, 255, 255),'f')/255.,
"Theta": np.array((255, 170, 238),'f')/255.,
"Lambda": np.array((128, 128, 128),'f')/255.,
"Xi": np.array((145, 95, 211),'f')/255.,
"Pi": np.array(( 95, 95, 211),'f')/255.,
"Sigma": np.array(( 85, 212, 0),'f')/255.,
"Phi": np.array((255, 179, 128),'f')/255.,
"Psi": np.array((255, 221, 85),'f')/255.}
SPECTRE_POINTS = np.array([(0.0, 0.0),
(1.0, 0.0),
(1.5, -np.sqrt(3)/2),
(1.5+np.sqrt(3)/2, 0.5-np.sqrt(3)/2),
(1.5+np.sqrt(3)/2, 1.5-np.sqrt(3)/2),
(2.5+np.sqrt(3)/2, 1.5-np.sqrt(3)/2),
(3+np.sqrt(3)/2, 1.5),
(3.0, 2.0),
(3-np.sqrt(3)/2, 1.5),
(2.5-np.sqrt(3)/2, 1.5+np.sqrt(3)/2),
(1.5-np.sqrt(3)/2, 1.5+np.sqrt(3)/2),
(0.5-np.sqrt(3)/2, 1.5+np.sqrt(3)/2),
(-np.sqrt(3)/2, 1.5),
(0.0, 1.0)], 'float32')
SPECTRE_QUAD = SPECTRE_POINTS[[3,5,7,11],:]
def mul(A, B):
AB = A.copy()
AB[:,:2] = A[:,:2].dot(B[:,:2])
AB[:,2] += A[:,:2].dot(B[:,2])
return AB
class Tile:
def __init__(self, label):
self.label = label
self.quad = SPECTRE_QUAD.copy()
def draw(self, polygons, tile_transformation=IDENTITY.copy()):
vertices = SPECTRE_POINTS.dot(tile_transformation[:,:2].T) + tile_transformation[:,2]
polygons.append((vertices, COLOR_MAP[self.label]))
class MetaTile:
def __init__(self, tiles=[], transformations=[], quad=SPECTRE_QUAD.copy()):
self.tiles = tiles
self.transformations = transformations
self.quad = quad
def draw(self, polygons, transformation=IDENTITY.copy()):
for tile, trsf in zip(self.tiles, self.transformations):
tile.draw(polygons, mul(transformation, trsf))
def buildSpectreBase():
ttrans = np.array([[1,0,SPECTRE_POINTS[8,0]],
[0,1,SPECTRE_POINTS[8,1]]])
trot = np.array([[np.cos(PI/6),-np.sin(PI/6),0.],
[np.sin(PI/6), np.cos(PI/6),0.]],'float32')
trsf = mul(ttrans, trot)
tiles = {}
tiles["Gamma"] = MetaTile(tiles=[Tile("Gamma1"),Tile("Gamma2")],
transformations=[IDENTITY.copy(),trsf],
quad=SPECTRE_QUAD.copy())
for label in TILE_NAMES:
if label != "Gamma":
tiles[label] = Tile(label)
return tiles
def buildSupertiles(input_tiles):
# First, use any of the nine-unit tiles in "tiles" to obtain a
# list of transformation matrices for placing tiles within supertiles.
quad = input_tiles["Delta"].quad
transformations = [IDENTITY.copy()]
total_angle = 0
trot = IDENTITY.copy()
transformed_quad = quad
for _angle, _from, _to in (( PI/3, 3, 1),
( 0., 2, 0),
( PI/3, 3, 1),
( PI/3, 3, 1),
( 0., 2, 0),
( PI/3, 3, 1),
(-2*PI/3, 3, 3)):
if _angle != 0:
total_angle += _angle
trot = np.array([[1, 0,0],[0,1,0]])*np.cos(total_angle) \
+np.array([[0,-1,0],[1,0,0]])*np.sin(total_angle)
transformed_quad = quad.dot(trot[:,:2].T) # + trot[:,2]
last_trsf = transformations[-1]
ttrans = IDENTITY.copy()
ttrans[:,2] = last_trsf[:,:2].dot(quad[_from,:]) + last_trsf[:,2] \
-transformed_quad[_to,:]
transformations.append(mul(ttrans, trot))
R = np.array([[-1,0,0],[ 0,1,0]], 'float32')
transformations = [ mul(R, trsf) for trsf in transformations ]
# Now build the actual supertiles, labeling appropriately.
super_quad = quad[[2,1,2,1],:]
for i,itrsf in enumerate([6,5,3,0]):
trsf = transformations[itrsf]
super_quad[i,:] = trsf[:,:2].dot(super_quad[i,:]) + trsf[:,2]
tiles = {}
for label, substitutions in (("Gamma", ("Pi", "Delta", None, "Theta", "Sigma", "Xi", "Phi", "Gamma")),
("Delta", ("Xi", "Delta", "Xi", "Phi", "Sigma", "Pi", "Phi", "Gamma")),
("Theta", ("Psi", "Delta", "Pi", "Phi", "Sigma", "Pi", "Phi", "Gamma")),
("Lambda", ("Psi", "Delta", "Xi", "Phi", "Sigma", "Pi", "Phi", "Gamma")),
("Xi", ("Psi", "Delta", "Pi", "Phi", "Sigma", "Psi", "Phi", "Gamma")),
("Pi", ("Psi", "Delta", "Xi", "Phi", "Sigma", "Psi", "Phi", "Gamma")),
("Sigma", ("Xi", "Delta", "Xi", "Phi", "Sigma", "Pi", "Lambda", "Gamma")),
("Phi", ("Psi", "Delta", "Psi", "Phi", "Sigma", "Pi", "Phi", "Gamma")),
("Psi", ("Psi", "Delta", "Psi", "Phi", "Sigma", "Psi", "Phi", "Gamma"))):
tiles[label] =\
MetaTile(tiles=[input_tiles[subst] for subst in substitutions if subst],
transformations=[trsf for subst, trsf in zip(substitutions, transformations) if subst],
quad=super_quad)
return tiles
start = time()
tiles = buildSpectreBase()
for _ in range(N_ITERATIONS):
tiles = buildSupertiles(tiles)
time1 = time()-start
print(f"supertiling loop took {round(time1, 4)} seconds")
start = time()
polygons = []
tiles["Delta"].draw(polygons)
time2 = time()-start
print(f"tile recursion loop took {round(time2, 4)} seconds, generated {len(polygons)} tiles")
plt.figure(figsize=(8, 8))
plt.axis('equal')
for pts,color in polygons:
plt.fill(pts[:,0],pts[:,1],facecolor=color)
plt.show()
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels