#!/usr/bin/python3 # Copyright (C) 2016 Florian Festi # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import sys, re from boxes import * import boxes class Layout(Boxes): """Generate a typetray from a layout file""" def __init__(self, input=None, webargs=False): Boxes.__init__(self) self.buildArgParser("h", "hi") if not webargs: self.argparser.add_argument( "--input", action="store", type=argparse.FileType('r'), help="layout file") self.argparser.add_argument( "--x", action="store", type=int, default=None, help="number of compartments side by side") self.argparser.add_argument( "--y", action="store", type=int, default=None, help="number of compartments back to front") else: self.argparser.add_argument( "--layout", action="store", type=str) def fillDefault(self, x, y): self.x = [0.0] * x self.y = [0.0] * y self.hwalls = [[True for i in range(x)] for j in range(y+1)] self.vwalls = [[True for i in range(x+1)] for j in range(y)] self.floors = [[True for i in range(x)] for j in range(y)] def __str__(self): r = [] for i, x in enumerate(self.x): r.append(" |" * (i) + " ,> %.1fmm\n" % x) for hwalls, vwalls, floors, y in zip( self.hwalls, self.vwalls, self.floors, self.y): r.append("".join(("+" + " -"[h] for h in hwalls)) + "+\n") r.append("".join((" |"[v] + "X "[f] for v, f in zip(vwalls, floors))) + " |"[vwalls[-1]] + " %.1fmm\n" % y) r.append("".join(("+" + " -"[h] for h in self.hwalls[-1])) + "+\n") return "".join(r) def vWalls(self, x, y): "Number of vertical walls at a crossing" result = 0 if y>0 and self.vwalls[y-1][x]: result += 1 if y < len(self.y) and self.vwalls[y][x]: result += 1 return result def hWalls(self, x, y): "Number of horizontal walls at a crossing" result = 0 if x>0 and self.hwalls[y][x-1]: result += 1 if x0 and self.floors[y][x-1]) or (x0 and self.floors[y-1][x]) or (y0 and self.floors[y-1][x]: # Inside Wall if self.hwalls[y][x]: self.fingerHolesAt(posx, posy+t2, self.x[x], angle=0) else: # Top edge self.edgeAt(e, posx+self.x[x], posy+t, self.x[x], -180) if x==0 or y==0 or not self.floors[y-1][x-1]: self.edgeAt("e", posx, posy+t, t, -180) if x==lx-1 or y==0 or not self.floors[y-1][x+1]: self.edgeAt("e", posx+self.x[x]+t, posy+t, t, -180) elif y>0 and self.floors[y-1][x]: # Bottom Edge self.edgeAt(e, posx, posy, self.x[x]) if x==0 or y==ly or not self.floors[y][x-1]: self.edgeAt("e", posx-t, posy, t) if x==lx-1 or y==ly or not self.floors[y][x+1]: self.edgeAt("e", posx+self.x[x], posy, t) posx += self.x[x] + self. thickness posy += self.y[y-1] + self.thickness posx = 0 for x in range(lx+1): posy = self.thickness for y in range(ly-1, -1, -1): if self.vwalls[y][x]: e = "F" else: e = "e" if x>0 and self.floors[y][x-1]: if x < lx and self.floors[y][x]: # Inside wall if self.vwalls[y][x]: self.fingerHolesAt(posx+t2, posy, self.y[y]) else: # Right edge self.edgeAt(e, posx+t, posy, self.y[y], 90) if x==lx or y==0 or not self.floors[y-1][x]: self.edgeAt("e", posx+t, posy+self.y[y], t, 90) if x==lx or y==ly-1 or not self.floors[y+1][x]: self.edgeAt("e", posx+t, posy-t, t, 90) elif x < lx and self.floors[y][x]: # Left edge self.edgeAt(e, posx, posy+self.y[y], self.y[y], -90) if x==0 or y==0 or not self.floors[y-1][x-1]: self.edgeAt("e", posx, posy+self.y[y]+t, t, -90) if x==0 or y==ly-1 or not self.floors[y+1][x-1]: self.edgeAt("e", posx, posy, t, -90) posy += self.y[y] + self.thickness if x < lx: posx += self.x[x] + self.thickness self.close() def parse(self, input): x = [] y = [] hwalls = [] vwalls = [] floors = [] for line in input: if not line or line[0] == "#": continue m = re.match(r"( \|)* ,>\s*(\d*\.?\d+)\s*mm\s*", line) if m: x.append(float(m.group(2))) continue if line[0] == '+': w = [] for n, c in enumerate(line): if n % 2: if c == ' ': w.append(False) elif c == '-': w.append(True) else: pass #raise ValueError(line) else: if c != '+': pass #raise ValueError(line) hwalls.append(w) if line[0] in " |": w = [] f = [] for n, c in enumerate(line[:len(x)*2+1]): if n % 2: if c == 'X': f.append(False) elif c == ' ': f.append(True) else: raise ValueError(line) else: if c == ' ': w.append(False) elif c == '|': w.append(True) else: raise ValueError(line) floors.append(f) vwalls.append(w) m = re.match(r"([ |][ X])+[ |]\s*(\d*\.?\d+)\s*mm\s*", line) if not m: raise ValueError(line) else: y.append(float(m.group(2))) # check sizes lx = len(x) ly = len(y) if len(hwalls) != ly+1: raise ValueError("Wrong number of horizontal wall lines: %i (%i expected)" % (len(hwalls), ly+1)) for nr, walls in enumerate(hwalls): if len(walls)!= lx: raise ValueError("Wrong number of horizontal walls in line %i: %i (%i expected)" % (nr, len(walls), lx)) if len(vwalls) != ly: raise ValueError("Wrong number of vertical wall lines: %i (%i expected)" % (len(vwalls), ly)) for nr, walls in enumerate(vwalls): if len(walls) != lx+1: raise ValueError("Wrong number of vertical walls in line %i: %i (%i expected)" % (nr, len(walls), lx+1)) self.x = x self.y = y self.hwalls = hwalls self.vwalls = vwalls self.floors = floors class LayoutGenerator(Layout): """Type tray with each wall and floor tile being optional""" def __init__(self): Boxes.__init__(self) self.argparser = boxes.ArgumentParser() self.argparser.add_argument( "--x", action="store", type=int, default=2, help="number of compartments side by side") self.argparser.add_argument( "--y", action="store", type=int, default=2, help="number of compartments back to front") def render(self): return def main(): l = Layout() l.parseArgs() if l.x and l.y: l.fillDefault(l.x, l.y) if l.output: with open(l.output, "w") as f: f.write(str(l)) else: print(l) elif l.input: l.parse(l.input) l.render() else: l.argparser.print_usage() if __name__ == '__main__': main()