Skip to content

Instantly share code, notes, and snippets.

@ZhanruiLiang
Created May 20, 2012 06:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZhanruiLiang/2757075 to your computer and use it in GitHub Desktop.
Save ZhanruiLiang/2757075 to your computer and use it in GitHub Desktop.
A set of python scripts to show the animation of the problem POJ1070: Deformed Wheel.
import pygame as pg
import sys
from pygame.locals import *
import subprocess as sb
W, H = 800, 600
x0, y0 = 400, 400
BgColor = (0xff, 0xff, 0xff, 0xff)
LineColor = (0, 0, 0, 0xff)
SCROLL_UP, SCROLL_DOWN = 4, 5
k = 3.
inputfile='map-poj1070-0002'
def onexit():
proc.kill()
sys.exitfunc = onexit
def init():
global screen, proc, font
pg.display.init()
pg.font.init()
screen = pg.display.set_mode((W, H), 0, 32)
proc = sb.Popen(['./a', inputfile], stdout=sb.PIPE, stderr=sb.PIPE, stdin=sb.PIPE)
font = pg.font.SysFont('monospace', 16)
lines = []
data = []
def fetch():
global waiting
while 1:
line = proc.stdout.readline()
if not line:
# eof
return
line = line.rstrip()
if line.startswith(':'):
line = line[1:]
if line == 'stroke':
waiting = 1
return
lines.append(line)
else:
print 'client: ', line
def send():
try:
proc.stdin.write(':\n')
proc.stdin.flush()
except IOError as e:
sys.stderr.write(proc.stderr.read())
print e
def tfp((x, y)):
return (int(k*x + x0), int(-y*k + y0))
def rtfp((x, y)):
return ((x - x0 - 0.)/k, (-y + y0 - 0.)/k)
def transform(ps):
return [tfp((x, y)) for x, y in ps]
cnt = 0
def draw():
global cnt, data, lines
cnt += 1
print 'draw', cnt
data = lines
lines = []
redraw()
def redraw():
global data
if not data: return
databk = data[:]
n = int(data.pop(0))
ps = transform([map(float, data.pop(0).split()) for i in xrange(n)])
g = tfp(map(float, data.pop(0).split()))
m = int(data.pop(0))
ps1 = transform([map(float, data.pop(0).split()) for i in xrange(m)])
screen.fill(BgColor)
pg.draw.polygon(screen, LineColor, ps, 1)
for i, p in enumerate(ps):
pg.draw.circle(screen, (255*i/n, 0, 0, 0xff), p, 4)
pg.draw.lines(screen, LineColor, 0, ps1, 1)
pg.draw.circle(screen, (0, 0, 0xff, 0xff), g, 4)
# draw the coordinate
pg.draw.circle(screen, (0, 0xff, 0, 0xff), tfp((0, 0)), 4)
screen.blit(txt, (0, 0))
pg.display.flip()
data = databk
init()
waiting = 0
pg.key.set_repeat(500, 50)
txt = pg.Surface((1, 1))
mpos = None
dx, dy = 0, 0
while 1:
for e in pg.event.get():
if e.type == QUIT:
exit(0)
if e.type == KEYDOWN:
if e.key == K_RETURN:
if waiting:
send()
waiting = 0
else:
print 'not waiting, ignored'
elif e.key == K_SPACE:
k = 3
x0 = 400
y0 = 400
redraw()
if e.key == K_q:
exit(0)
if e.type == MOUSEBUTTONDOWN:
if e.button in (SCROLL_UP, SCROLL_DOWN):
x, y = rtfp(e.pos)
dk = 0.1
if e.button == SCROLL_UP:
k *= (1+dk)
if e.button == SCROLL_DOWN:
k /= (1+dk)
x0 = e.pos[0] - k * x
y0 = e.pos[1] + k * y
redraw()
if e.button == 1:
txt = font.render("(%.1f, %.1f)" % rtfp(e.pos), 1, (0, 0, 0, 0xff), BgColor)
redraw()
elif e.type == MOUSEMOTION:
if e.buttons[0]:
dx += e.rel[0]
dy += e.rel[1]
if dx*dx+dy*dy > 40:
x0, y0 = x0 + dx, y0 + dy
dx, dy = 0, 0
redraw()
if not waiting:
fetch()
if lines:
draw()
import pygame as pg
import sys, os
from pygame.locals import *
import subprocess as sb
W, H = 1200, 800
x0, y0 = 400, 400
BgColor = (0xff, 0xff, 0xff, 0xff)
LineColor = (0, 0, 0, 0xff)
SCROLL_UP, SCROLL_DOWN = 4, 5
k = 3.
poly = []
gra = None
hill = []
pbuf = []
def init():
global screen, proc, font
pg.display.init()
pg.font.init()
screen = pg.display.set_mode((W, H), 0, 32)
font = pg.font.SysFont('monospace', 12)
def tfp((x, y)):
return (int(k*x + x0), int(-y*k + y0))
def rtfp((x, y)):
return ((x - x0 - 0.)/k, (-y + y0 - 0.)/k)
def transform(ps):
return [tfp((x, y)) for x, y in ps]
def inform(msg):
h = 0
txt.fill((0, 0, 0, 0))
for line in msg.split('\n'):
txtline = font.render(line, 1, LineColor)
txt.blit(txtline, (5, h))
h += font.size(line)[1]
redraw()
print msg
def add_point(p):
pbuf.append(p)
inform("add point at (%.2f, %.2f)" % p)
def collect_poly():
while len(pbuf) > 1:
poly.append(pbuf.pop(0))
global gra
gra = pbuf.pop(0)
inform("polygon collected\ngravity center collected\n")
def collect_hill():
while len(pbuf):
hill.append(pbuf.pop(0))
def dist(a, b):
return ((a[0] - b[0])**2 + (a[1] - b[1])**2)**0.5
def collect_save():
prefix = 'map-poj1070-%04d'
for i in xrange(1000):
fn = prefix % i
if not os.path.exists(fn):
pg.image.save(screen, fn + '.png')
with open(fn, 'w') as fout:
print >> fout, 1
print >> fout, len(poly)
print >> fout, '\n'.join('%.2f %.2f' % p for p in poly)
print >> fout, '%.2f %.2f' % gra
endp = None
for p in poly:
if endp is None or dist(endp, hill[0]) > dist(p, hill[0]):
endp = p
hill[0] = endp
x0, y0 = endp
for x, y in hill[1:]:
k = (y - y0)/(x - x0 - 0.)
if k < -1e-8:
print 'WARNING: DATA INVALID. k = %s => k = 0, expected k >= 0' % (k,)
k = 0
l = ((y-y0)**2+(x-x0)**2)**0.5
print >> fout, '%.2f %.2f' % (l, k)
x0, y0 = x, y
print >> fout, '%.2f %.2f' % endp
inform("saved as %s and %s.png" % (fn, fn))
break
else:
inform("can not save, too many files")
def redraw():
screen.fill(BgColor)
for p in pbuf:
pg.draw.circle(screen, (0xff, 0, 0, 0xff), tfp(p), 3)
if poly:
# draw poly
pg.draw.polygon(screen, LineColor, transform(poly), 1)
pg.draw.circle(screen, (0, 0, 0xff, 0xff), tfp(gra), 4)
if hill:
pg.draw.lines(screen, LineColor, 0, transform(hill), 1)
pg.draw.circle(screen, (0, 0xff, 0, 0xff), tfp((0, 0)), 4)
pg.draw.circle(screen, (0, 0, 0, 0xff), tfp((100, 100)), 4)
screen.blit(txt, (0, 0))
pg.display.flip()
init()
# pg.key.set_repeat(500, 50)
txt = pg.Surface((500, 300)).convert_alpha()
mpos = None
dx, dy = 0, 0
helpMsg = """Welcome the the data maker of poj1070: Deformed Wheel
Use left mouse button to add new point
Use backspace to undo
Use mouse scroll to zoom
Drag with right mouse button to navigate
Use spacebar to reset the view
Use enter to goto next state, note this can not be undo
Press F1 to show this message
"""
inform(helpMsg)
collectors = [collect_poly, collect_hill, collect_save]
timer = pg.time.Clock()
while 1:
for e in pg.event.get():
if e.type == QUIT:
exit(0)
if e.type == KEYDOWN:
if e.key == K_SPACE:
# reset view
k = 3
x0 = 400
y0 = 400
redraw()
if e.key == K_q:
exit(0)
if e.key == K_F1:
inform(helpMsg)
if e.key == K_RETURN:
collector = collectors.pop(0)
collector()
if e.key == K_BACKSPACE:
if pbuf:
pbuf.pop()
redraw()
if e.type == MOUSEBUTTONDOWN:
if e.button in (SCROLL_UP, SCROLL_DOWN):
# zoom
x, y = rtfp(e.pos)
dk = 0.1
if e.button == SCROLL_UP:
k *= (1+dk)
if e.button == SCROLL_DOWN:
k /= (1+dk)
x0 = e.pos[0] - k * x
y0 = e.pos[1] + k * y
redraw()
if e.button == 1:
add_point(rtfp(e.pos))
redraw()
elif e.type == MOUSEMOTION:
if e.buttons[2]:
dx += e.rel[0]
dy += e.rel[1]
if dx*dx+dy*dy > 40:
x0, y0 = x0 + dx, y0 + dy
dx, dy = 0, 0
redraw()
redraw()
timer.tick(30)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment