from collections import deque
import time
def createCirclesAround(n): return matrix([
[1, 0, 0, 0],
[0, 0, 1, 0],
[4*cos(pi/n)^2, 1, 4*cos(pi/n)^2, 4*cos(pi/n)],
[-2*cos(pi/n), 0, -2*cos(pi/n), -1]
])
def changeHub(n): return matrix([
[0, 1, 0, 0],
[0, 0, 1, 0],
[1, 0, 0, 0],
[0, 0, 0, 1]
])
def changePerspective(n) : return matrix([
[1, 0, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, -1]
])
def rotate(n, k) : return matrix([
[cos(k*2*pi/n), sin(k*2*pi/n)],
[-sin(k*2*pi/n), cos(k*2*pi/n)]
])
def startingValues(n): return matrix([
[0, 0, 1/(1-sin(pi/n))],
[cos(4*pi/n)*csc(pi/n), sin(4*pi/n)*csc(pi/n), csc(pi/n)],
[cos(2*pi/n)*csc(pi/n), sin(2*pi/n)*csc(pi/n), csc(pi/n)],
[-cos(3*pi/n)*csc(pi/n), -1-2*cos(2*pi/n), cot(pi/n)/(-1+sin(pi/n))]
])
def createCircles(n, maxDepth, maxCDepth, withC, colors):
class CircleInfo:
def __init__(self, S, depth, depthBeforeC, lastOne, initialC, isC, isFirstC, colorOrder):
self.S = S
self.lastOne = lastOne
self.initialC = initialC
self.depth = depth
self.depthBeforeC = depthBeforeC
self.isC = isC
self.isFirstC = isFirstC
self.colorOrder = colorOrder
# precompute powers of A and B to reduce amount of matrix multiplication - cut time in half
A = []
for x in range(0,n):
A.append(N(createCirclesAround(n))^x)
B = []
for x in range(0,3):
B.append(N(changeHub(n))^x)
C = N(changePerspective(n))
AB = A[1]*B[1] #A*B
BC = B[1]*C #B*C
BBC = B[2]*C #B^2*C
startVals = N(startingValues(n))
stack = []
f = file(DATA + 'test.csv', 'w')
curvature = (startVals)[0][2]
xCoord = (startVals)[0][0]/curvature
yCoord = (startVals)[0][1]/curvature
circle = '%.30f' % xCoord + ',' + '%.30f' % yCoord + ',' + '%.30f' % curvature + ',' + str(colors[0]) + '\r\n'
f.write(circle)
stack.append(CircleInfo(startVals, 0, 0, False, True, False, True, deque(colors)))
while (stack != []):
pop = stack.pop()
depth = pop.depth
depthBeforeC = pop.depthBeforeC
initialC = pop.initialC
isC = pop.isC
isFirstC = pop.isFirstC
lastOne = pop.lastOne
S = pop.S
colorOrder = pop.colorOrder
if (isC and isFirstC and depth > 0):
depthBeforeC = depth
depth = 1
isFirstC = False
if (not isC and depth >= maxDepth):
continue
elif (isC and depth >= maxCDepth - depthBeforeC + 2):
continue
elif (isC and depth >= 4):
continue
if (depth == 0):
lower = 0
upper = n
elif (initialC):
lower = 2
upper = n - 1
initialC = False
elif (depth > 1 and lastOne):
lower = 2
upper = n - 3
lastOne = False
if (withC):
Z = AB*S
newColorOrder = deque(colorOrder)
newColorOrder.rotate(-1) # B
left = newColorOrder.pop() #
right = newColorOrder.pop() #
newColorOrder.append(left) #
newColorOrder.append(right) # all A
left = newColorOrder.pop() #
right = newColorOrder.pop() #
newColorOrder.append(left) #
newColorOrder.append(right) # all C
stack.append(CircleInfo(C*Z, depth, depthBeforeC, False, True, True, isFirstC, deque(newColorOrder)))
newColorOrder.rotate(-1) # B
stack.append(CircleInfo(BC*Z, depth, depthBeforeC, False, True, True, isFirstC, deque(newColorOrder)))
newColorOrder.rotate(-1) # B
stack.append(CircleInfo(BBC*Z, depth, depthBeforeC, False, True, True, isFirstC, deque(newColorOrder)))
else:
lower = 2
upper = n - 2
for x in range(lower, upper):
Z = A[x]*S
newColorOrder = deque(colorOrder)
newNColorOrder = deque(colorOrder)
color = colorOrder[2]
if (depth == 0 or x != 0):
left = colorOrder.pop()
right = colorOrder.pop()
colorOrder.append(left)
colorOrder.append(right)
curvature = (Z)[2][2]
xCoord = (Z)[2][0]/curvature
yCoord = (Z)[2][1]/curvature
circle = '%.30f' % xCoord + ',' + '%.30f' % yCoord + ',' + '%.30f' % curvature + ',' + str(color) + '\r\n'
f.write(circle)
if (withC):
left = newColorOrder.pop() #
right = newColorOrder.pop() #
newColorOrder.append(left) #
newColorOrder.append(right) # all C
stack.append(CircleInfo(C*Z, depth+1, depthBeforeC, False, True, True, isFirstC, deque(newColorOrder)))
newColorOrder.rotate(-1) # B
stack.append(CircleInfo(BC*Z, depth+1, depthBeforeC, False, True, True, isFirstC, deque(newColorOrder)))
newColorOrder.rotate(-1) # B
stack.append(CircleInfo(BBC*Z, depth+1, depthBeforeC, False, True, True, isFirstC, deque(newColorOrder)))
newNColorOrder.rotate(-2) # B^2
stack.append(CircleInfo(B[2]*Z, depth+1, depthBeforeC, x == upper - 1, False, isC, isFirstC, deque(newNColorOrder)))
if (withC and depth == maxDepth - 1):
Z = A[upper]*S
newColorOrder = deque(colorOrder)
left = newColorOrder.pop() #
right = newColorOrder.pop() #
newColorOrder.append(left) #
newColorOrder.append(right) # all C
stack.append(CircleInfo(C*Z, depth+1, depthBeforeC, False, True, True, isFirstC, deque(newColorOrder)))
newColorOrder.rotate(-1) # B
stack.append(CircleInfo(BC*Z, depth+1, depthBeforeC, False, True, True, isFirstC, deque(newColorOrder)))
newColorOrder.rotate(-1) # B
stack.append(CircleInfo(BBC*Z, depth+1, depthBeforeC, False, True, True, isFirstC, deque(newColorOrder)))
def addAllBranches(circles, n, colors):
R = []
for x in range(0, n):
R.append(N(rotate(n, x)))
for i in range(1, len(circles)): #dont do with first one in circles
for x in range (1, n):
color = circles[i][3]
if (x % 2 == 1):
if (color == colors[2]):
color = colors[1]
elif (color == colors[1]):
color = colors[2]
newCircle = matrix([circles[i][0], circles[i][1]])*R[x]
circles.append([newCircle[0][0], newCircle[0][1], circles[i][2], color])
def addNumsToPlot(n, circles, fontSize):
k = 0
numList = Graphics()
for c in circles:
numList += text(k,(c[0],c[1]), fontsize = fontSize) # make branches
if (k == (len(circles)-1)/n):
k = 0
k += 1
return numList
def addLinesToPlot(n, circles):
lineList = Graphics()
for x in range(0, len(circles) - 1):
lineList += line([(circles[x][0],circles[x][1]),(circles[x+1][0],circles[x+1][1])])
return lineList