advent2023/animate_zweiundzwanzig.py

99 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env python3
from useful import *
from rtree import index
def cubeize(line, i):
x, y, z, u, v, w = numbers(line)
return (x, y, z, u + .9, v + .9, w + 1, i)
def is_supported(tree, block):
for g in tree.intersection(block):
if grounded[g][5] == block[2]:
return True
def assign_touching_ground_to_ground():
global gtree, grounded, moving
touching = True
while touching:
touching = False
for i, m in enumerate(moving):
if is_supported(gtree, m[:6]):
moving = np.append(moving[:i], moving[i+1:], axis=0)
gtree.insert(len(grounded), m[:6])
grounded = np.append(grounded, [m, ], axis=0)
touching = True
break
def draw():
global frame
with open('22_%03d.pov' % frame, 'w') as f:
f.write('''#include "colors.inc"
global_settings { assumed_gamma 1.5 }
camera {
location <%s, %s, %s>
look_at <5, %s, 5>
up y
right x
}
light_source { 0 rgb 1
looks_like {
sphere { 0, 3
pigment { rgb 1 }
finish { ambient 1 diffuse 0 }
}
}
translate <666, 666, -222>
}
''' % (frame * .15, 22 + frame * .15, -15 - frame * .225, 10 + frame * .125))
for c in grounded:
f.write('''superellipsoid {
<.1, .1>
translate <1, 1, 1>
scale <.5, .5, .5>
scale <%s, %s, %s>
translate <%s, %s, %s>
pigment { color Gray80 }
}
''' % (c[3] - c[0], c[5] - c[2], c[4] - c[1], c[0], c[2], c[1]))
for i, c in enumerate(moving[::-1]):
f.write('''superellipsoid {
<.1, .1>
translate <1, 1, 1>
scale <.5, .5, .5>
scale <%s, %s, %s>
translate <%s, %s, %s>
pigment { color %s }
}
''' % (c[3] - c[0], c[5] - c[2], c[4] - c[1], c[0], c[2], c[1],
'Red Green Blue Orange Magenta Cyan Yellow'.split()[int(c[6])%7]))
frame += 1
frame = 0
unsortedcubes = np.asarray([cubeize(l, i) for i, l in enumerate(lines(open(0)))])
# sorting makes O(n²) movement closer to O(nlogn) or whatever
moving = np.asarray(sorted(unsortedcubes, key=lambda a: a[2]))
# just create the ground. max of our input happens to be 278.
grounded = np.asarray([(-666, -666, 0, 666, 666, 1, 0)])
gtree = index.Index(properties=index.Property(dimension=3))
gtree.insert(0, grounded[0][:6])
# also find the ones touching ground
assign_touching_ground_to_ground()
draw()
# drop stuff
while len(moving):
moving += np.asarray([0, 0, -.25, 0, 0, -.25, 0])
assign_touching_ground_to_ground()
draw()