|
|
@ -3,6 +3,8 @@
|
|
|
|
import cairo
|
|
|
|
import cairo
|
|
|
|
import math
|
|
|
|
import math
|
|
|
|
import random
|
|
|
|
import random
|
|
|
|
|
|
|
|
import threading
|
|
|
|
|
|
|
|
import time
|
|
|
|
from utils import circle_fill
|
|
|
|
from utils import circle_fill
|
|
|
|
from utils import random_color
|
|
|
|
from utils import random_color
|
|
|
|
from pixelflut import surface_to_pixelflut
|
|
|
|
from pixelflut import surface_to_pixelflut
|
|
|
@ -13,6 +15,9 @@ ANGLE_RANDOM_MAX = 0.6
|
|
|
|
# how much to shrink each consecutive circle
|
|
|
|
# how much to shrink each consecutive circle
|
|
|
|
SHRINK = 0.00002
|
|
|
|
SHRINK = 0.00002
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hitmap = list()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Branch():
|
|
|
|
class Branch():
|
|
|
|
def __init__(self, idx, ctx, x, y, r, ang):
|
|
|
|
def __init__(self, idx, ctx, x, y, r, ang):
|
|
|
|
#ctx.set_source_rgb(255, 0, 0)
|
|
|
|
#ctx.set_source_rgb(255, 0, 0)
|
|
|
@ -40,7 +45,7 @@ class Branch():
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
# did we hit canvas edge?
|
|
|
|
# did we hit canvas edge?
|
|
|
|
# if next_x + next_r > 1 or next_x - next_r < 0:
|
|
|
|
# if next_x + next_r > 1 or next_x - next_r < 0:
|
|
|
|
if (math.pow(next_x - 0.5, 2) + math.pow(next_y - 0.5, 2)) > math.pow(0.4, 2):
|
|
|
|
if (math.pow(next_x - 0.5, 2) + math.pow(next_y - 0.5, 2)) > math.pow(0.5, 2):
|
|
|
|
self.ended = True
|
|
|
|
self.ended = True
|
|
|
|
return False
|
|
|
|
return False
|
|
|
|
if next_y + next_r > 1 or next_y - next_r < 0:
|
|
|
|
if next_y + next_r > 1 or next_y - next_r < 0:
|
|
|
@ -81,39 +86,60 @@ class Node():
|
|
|
|
def __ne__(self, other):
|
|
|
|
def __ne__(self, other):
|
|
|
|
return self.x != other.x or self.y != other.y or self.r != other.r or self.ang != other.ang
|
|
|
|
return self.x != other.x or self.y != other.y or self.r != other.r or self.ang != other.ang
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def grow_sub(ctx, branch, branches, new_subs):
|
|
|
|
|
|
|
|
# create a sub branch based on length
|
|
|
|
|
|
|
|
sub_branches = len(branch.nodes) // 7 * 2
|
|
|
|
|
|
|
|
if sub_branches == 0: return
|
|
|
|
|
|
|
|
#sub_branches = 4
|
|
|
|
|
|
|
|
#print(f'creating {sub_branches} subs')
|
|
|
|
|
|
|
|
for i in range(sub_branches):
|
|
|
|
|
|
|
|
for n in range(60): # attempts at growing branches
|
|
|
|
|
|
|
|
start_node = random.choice(branch.nodes)
|
|
|
|
|
|
|
|
# start perpendicular to our last angle
|
|
|
|
|
|
|
|
start_angle = start_node.ang + random.choice([90, -90]) + random.uniform(-30, 30)
|
|
|
|
|
|
|
|
start_x = (start_node.r * 1.2) * math.sin(start_angle) + start_node.x
|
|
|
|
|
|
|
|
start_y = (start_node.r * 1.2) * math.cos(start_angle) + start_node.y
|
|
|
|
|
|
|
|
start_r = start_node.r * 0.8
|
|
|
|
|
|
|
|
new_branch = Branch(0, ctx, start_x, start_y, start_r, start_angle)
|
|
|
|
|
|
|
|
if new_branch.place_next(branches):
|
|
|
|
|
|
|
|
break
|
|
|
|
|
|
|
|
new_branch.set_ignores(branch.nodes)
|
|
|
|
|
|
|
|
branches.append(new_branch)
|
|
|
|
|
|
|
|
new_subs.append(new_branch)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def grow_branch_until_ended(branch, branches):
|
|
|
|
|
|
|
|
while not branch.ended:
|
|
|
|
|
|
|
|
branch.place_next([b for b in branches if b != branch])
|
|
|
|
|
|
|
|
|
|
|
|
def grow_subs(ctx, subs, branches):
|
|
|
|
def grow_subs(ctx, subs, branches):
|
|
|
|
source = ctx.get_source()
|
|
|
|
source = ctx.get_source()
|
|
|
|
new_subs = []
|
|
|
|
new_subs = []
|
|
|
|
created = False
|
|
|
|
threads = list()
|
|
|
|
|
|
|
|
print('spawning sub growing threads')
|
|
|
|
for branch in subs:
|
|
|
|
for branch in subs:
|
|
|
|
# create a sub branch based on length
|
|
|
|
# x = threading.Thread(target=grow_sub, args=(ctx, branch, branches, new_subs))
|
|
|
|
sub_branches = len(branch.nodes) // 7 * 2
|
|
|
|
# threads.append(x)
|
|
|
|
#print(f'creating {sub_branches} subs')
|
|
|
|
# x.start()
|
|
|
|
if sub_branches > 1:
|
|
|
|
grow_sub(ctx, branch, branches, new_subs)
|
|
|
|
created = True
|
|
|
|
#for tidx, thread in enumerate(threads):
|
|
|
|
|
|
|
|
# thread.join()
|
|
|
|
for i in range(sub_branches):
|
|
|
|
print('all threads finished')
|
|
|
|
for n in range(60): # attempts at growing branches
|
|
|
|
print('starting place_next threads')
|
|
|
|
start_node = random.choice(branch.nodes)
|
|
|
|
pl_threads = list()
|
|
|
|
# start perpendicular to our last angle
|
|
|
|
for branch in new_subs:
|
|
|
|
start_angle = start_node.ang + random.choice([90, -90]) + random.uniform(-30, 30)
|
|
|
|
x = threading.Thread(target=grow_branch_until_ended, args=(branch, branches))
|
|
|
|
start_x = (start_node.r * 1.2) * math.sin(start_angle) + start_node.x
|
|
|
|
pl_threads.append(x)
|
|
|
|
start_y = (start_node.r * 1.2) * math.cos(start_angle) + start_node.y
|
|
|
|
x.start()
|
|
|
|
start_r = start_node.r * 0.8
|
|
|
|
for tidx, thread in enumerate(pl_threads):
|
|
|
|
new_branch = Branch(i, ctx, start_x, start_y, start_r, start_angle)
|
|
|
|
thread.join()
|
|
|
|
if new_branch.place_next(branches):
|
|
|
|
print('place_next done')
|
|
|
|
break
|
|
|
|
|
|
|
|
new_branch.set_ignores(branch.nodes)
|
|
|
|
#while not all([branch.ended for branch in new_subs]):
|
|
|
|
branches.append(new_branch)
|
|
|
|
# for branch in new_subs:
|
|
|
|
new_subs.append(new_branch)
|
|
|
|
# branch.place_next([b for b in branches if b != branch])
|
|
|
|
if not created:
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
while not all([branch.ended for branch in new_subs]):
|
|
|
|
|
|
|
|
for branch in new_subs:
|
|
|
|
|
|
|
|
branch.place_next([b for b in branches if b != branch])
|
|
|
|
|
|
|
|
return new_subs
|
|
|
|
return new_subs
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
def main():
|
|
|
|
|
|
|
|
|
|
|
|
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
|
|
|
|
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
|
|
|
|
ctx = cairo.Context(surface)
|
|
|
|
ctx = cairo.Context(surface)
|
|
|
|
|
|
|
|
|
|
|
@ -132,6 +158,7 @@ def main():
|
|
|
|
branches.append(Branch(2, ctx, 0.6, 0.5, start_r, 90))
|
|
|
|
branches.append(Branch(2, ctx, 0.6, 0.5, start_r, 90))
|
|
|
|
branches.append(Branch(3, ctx, 0.5, 0.6, start_r, 0))
|
|
|
|
branches.append(Branch(3, ctx, 0.5, 0.6, start_r, 0))
|
|
|
|
# grow initial branches
|
|
|
|
# grow initial branches
|
|
|
|
|
|
|
|
print('growing initial branches')
|
|
|
|
while not all([b.ended for b in branches]):
|
|
|
|
while not all([b.ended for b in branches]):
|
|
|
|
for branch in branches:
|
|
|
|
for branch in branches:
|
|
|
|
branch.place_next(branches)
|
|
|
|
branch.place_next(branches)
|
|
|
@ -145,7 +172,12 @@ def main():
|
|
|
|
r, g, b = random_color()
|
|
|
|
r, g, b = random_color()
|
|
|
|
ctx.set_source_rgb(r, g, b)
|
|
|
|
ctx.set_source_rgb(r, g, b)
|
|
|
|
subs = grow_subs(ctx, subs, branches)
|
|
|
|
subs = grow_subs(ctx, subs, branches)
|
|
|
|
surface_to_pixelflut(surface)
|
|
|
|
print(f'iteration {x} done, sending to pixelflut')
|
|
|
|
|
|
|
|
x = threading.Thread(target=surface_to_pixelflut, args=(surface,))
|
|
|
|
|
|
|
|
x.daemon = True
|
|
|
|
|
|
|
|
x.start()
|
|
|
|
|
|
|
|
x.join()
|
|
|
|
|
|
|
|
#surface_to_pixelflut(surface)
|
|
|
|
#surface.write_to_png("out/hyphae.png") # Output to PNG
|
|
|
|
#surface.write_to_png("out/hyphae.png") # Output to PNG
|
|
|
|
#input('next')
|
|
|
|
#input('next')
|
|
|
|
finally:
|
|
|
|
finally:
|
|
|
|