Commit 4870dc60 authored by Kasalehlia's avatar Kasalehlia

add routers, implement tree_area, add gitignore

parent f29501e3
*.swp
*.pyc
import routers as routers_module
routers = [getattr(routers_module,r) for r in routers_module.__all__]
used = dict(zip([r.__name__ for r in routers], [0]*len(routers)))
def sectionToPath(sec):
"""calculates the stitching path for this section,
returning a list of positions to be stitched"""
if len(sec) == 1: # single pixel
a = sec.pop()
return [a,a+(1,1),a+(0,1),a+(1,0)]
line = normalizeLine(sec)
if line:
return pathForLine(line)
else:
#raise ValueError('Image contains currently unsupported sections')
#print "unsupported section"
#return [(0,0),(0,0)]
return reduce(lambda a,b: a+b, map(lambda a:[a,a+(1,1),a+(0,1),a+(1,0)], sorted(sec, key=lambda x:x[1])))
# SECTION TYPES ROUTING
def pathForLine(sec):
pass
def pathForMultiLine(sec):
pass
def t(val):
return val if type(val) == tuple else (val,)
options = sorted([(r,)+t(r.rate(sec)) for r in routers], key=lambda x: x[1], reverse=True)
router = options[0]
used[router[0].__name__] += 1
return router[0].route(sec, *router[2:])
# SECTIONS
......@@ -88,9 +78,37 @@ def getAdjacent(section, target):
index = section.index(target)
return [section[i] for i in range(len(section)) if abs(i-index) == 1]
def pixelByStiches(a,b):
"""returns a pixel identified by two stiches"""
diff = (a-b).abs()
if diff[0] in [0,1] and diff[1] in [0,1]:
return Tp(min(c,d) for c,d in zip(a,b))
return None
def crossPixel(pixel, corner):
"""takes a pixel and an adjacent stitch and returns the stitch to cross the pixel"""
if corner in [pixel+(i,j) for i in [0,1] for j in [0,1]]:
diff = corner-pixel
if diff[0] == diff[1]:
return pixel+(diff-(1,1)).abs()
else:
return pixel+diff.swap()
else:
return None
def T(a,b):
return Tp((a,b))
class Tp(tuple):
def __add__(self, other):
return Tp(x + y for x, y in zip(self, other))
def __sub__(self, other):
return Tp(x - y for x, y in zip(self, other))
def abs(self):
return Tp(abs(c) for c in self)
def swap(self):
return Tp(reversed(self))
......@@ -23,6 +23,8 @@ def start(png_file, background):
# PROCESS SECTIONS
output = list(buildPaths(sections, width, pixels))
print cs.used
printAsSvg("out.svg", output, metadata['palette'])
return
......@@ -60,7 +62,8 @@ def printAsSvg(svgFile, paths, palette):
maxX, maxY = (0,0)
stitches = 0
for i in paths:
assert i[1] is not None and len(i[1]) > 0
if i[1] is None or len(i[1]) == 0:
continue
out += ' <polyline points="'
for dx,dy in i[1]:
out += str(dx*10)+","+str(dy*10)+" "
......
from os.path import dirname, basename, isfile
import glob
modules = glob.glob(dirname(__file__)+"/*.py")
__all__ = [basename(f)[:-3] for f in modules if isfile(f) and not f.endswith('__init__.py')]
for mod in __all__:
__import__('routers.'+mod)
def rate(sec):
return 0
def route(sec):
return []
def rate(sec):
return 1
def route(sec):
return reduce(lambda a,b: a+b, map(lambda a:[a,a+(1,1),a+(0,1),a+(1,0)], sorted(sec, key=lambda x:x[1])))
def rate(sec):
return (len(sec) in [0,1])*100
def route(sec):
if len(sec) == 0:
return []
if len(sec) == 1:
a = iter(sec).next()
return [a,a+(1,1),a+(0,1),a+(1,0)]
def rate(sec):
flipped = False
x_min, x_max, y_min, y_max = _boundaries(sec)
height = y_max - y_min + 1
# try to find two columns going all the way (requisite)
for x in range(x_min, x_max):
if len(_pixel_in_column(sec, x)) == height and len(_pixel_in_column(sec, x+1)) == height:
break
else:
# flip and try again (no need to flip back)
sec = _flip(sec)
flipped = True
x_min, x_max, y_min, y_max = _boundaries(sec)
height = y_max - y_min + 1
for x in range(x_min, x_max):
if len(_pixel_in_column(sec, x)) == height and len(_pixel_in_column(sec, x+1)) == height:
break
else:
return 0
sec = set(sec)
for cy in range(y_min, y_max+1):
# walk left
for cx in range(x, x_min-1, -1):
if (cx, cy) in sec:
sec.discard((cx,cy))
else:
break
# walk right
for cx in range(x+1, x_max+1):
if (cx, cy) in sec:
sec.discard((cx,cy))
else:
break
if len(sec) == 0:
# extra lines: 2*height
return 100, x, flipped
else:
return 0
def route(sec, trunk, flipped):
sec = set(_flip(sec)) if flipped else set(sec)
x_min, x_max, y_min, y_max = _boundaries(sec)
path = [(trunk+1,y_min)]
# go down right trunk, walk to the right and back to the trunk
for cy in range(y_min, y_max+1):
ff = 0 # flipflop
# walk right
stop = x_max
for cx in range(trunk+1, x_max+2): # deliberately walk too far
ff = not ff
if (cx,cy) in sec:
path.append((cx+1,cy+ff))
else:
path.append((cx,cy+ff))
stop = cx-1
break
# walk back
for cx in range(stop, trunk, -1):
ff = not ff
path.append((cx,cy+ff))
assert ff == 1
for cy in range(y_max, y_min-1, -1):
ff = 1
# walk left
stop = x_min
for cx in range(trunk, x_min-2, -1):
ff = not ff
if (cx,cy) in sec:
path.append((cx,cy+ff))
else:
path.append((cx+1,cy+ff))
stop = cx+1
break
# walk back
for cx in range(stop, trunk+1):
ff = not ff
path.append((cx+1,cy+ff))
if flipped:
path = [(t[1],t[0]) for t in path]
return path
def _pixel_in_column(sec, x):
"""returns a set of pixels in a specific column"""
return [p for p in sec if p[0] == x]
def _boundaries(sec):
return min(sec, key=lambda a: a[0])[0], max(sec, key=lambda a: a[0])[0], min(sec, key=lambda a: a[1])[1], max(sec, key=lambda a: a[1])[1]
def _flip(sec):
return [t.swap() for t in sec]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment