# -*- coding: utf-8 -*- from __future__ import division import serial import math class Command: inicoms= ("IN", "SP", "LT") scalecoms=("PA", "PD", "PR", "PU", "CI" ) movecoms=("PA", "PD", "PR", "PU" ) def __init__(self, name, *args): self.name = name # hpgl Command name e.g. PU, PA, self.args = args # list of Position args @property def scalable(self): return True \ if self.name in Command.scalecoms and self.args else \ False @property def movable(self): return True \ if self.name in Command.movecoms and self.args else \ False @property def x(self): return self.args[0] \ if self.movable else\ None @property def y(self): return self.args[1] \ if self.movable else\ None def __len__(self): return len(str(self)) def __str__(self): return self.name + ",".join(str(arg) for arg in self.args) + ";" def __mul__(self, factor): if not self.scalable: return self if type(factor) == type(0) or type(factor) == type(0.0): factor = (factor, factor) return Command(self.name, int(self.args[0] * factor[0]), int(self.args[1] * factor[1])) \ if len(self.args)>1 else\ Command(self.name,int(self.args[0]*factor[0]) ) def __add__(self, addend): if not self.movable: return self if type(addend) == type(0) or type(addend) == type(0.0): addend = (addend, addend) return Command(self.name, int(self.x + addend[0]), int(self.y + addend[1])) def __sub__(self, addend): if type(addend) == type(0) or type(addend) == type(0.0): addend = (addend, addend) return self + (-addend[0], -addend[1]) def rotate(self, angl): if not self.movable: return self cosa=math.cos(angl*math.pi/180) sina=math.sin(angl*math.pi/180) return Command(self.name,int(self.x*cosa-self.y*sina),int(self.y*cosa+self.x*sina)) def flip(self): if not self.movable: return self return Command(self.name,self.y,-self.x) class Program: def __init__(self, commands=[]): self.commands = commands def parsefile(self, filename): with open(filename) as file: self.parse( file.read()) def parse(self, code): for command in code.strip().split(";")[:-1]: name, args = command[:2], command[2:] args = [int(arg) for arg in args.split(",")] if args else [] #print name , args self.commands.append(Command(name, *args)) def __str__(self): return "".join(str(command) for command in self.commands) def __mul__(self, arg): return Program([command * arg for command in self.commands]) def __add__(self, arg): return Program([command + arg for command in self.commands]) def __sub__(self, arg): return Program([command - arg for command in self.commands]) def __len__(self): return len(str(self)) def rotate(self, angl): return Program([command.rotate(angl) for command in self.commands]) def flip(self): return Program([command.flip() for command in self.commands]) @property def xmax(self): return max(command.x for command in self.commands if command.x and command.movable) @property def xmin(self): return min(command.x for command in self.commands if command.x and command.movable) @property def ymax(self): return max(command.y for command in self.commands if command.y and command.movable) @property def ymin(self): return min(command.y for command in self.commands if command.y and command.movable) @property def center(self): return int((self.xmin+self.xmax)/2),int((self.ymin+self.ymax)/2) @property def size(self): return self.xmax-self.xmin , self.yax - self.ymin @property def winsize(self): return self.xmax-self.xmin , self.ymax - self.ymin class Plotter: def __init__(self): self.p0incenter = False s=self.getoutput('OW;') print s if not s: self.__boundaries = -2000,-2000,2000,2000 self.ser=None else: self.__boundaries = tuple(int(x) for x in "".join(s).split(",")) def getoutput(self,outstr): try: self.ser = serial.Serial('/dev/ttyUSB0',timeout=15) print 'try to get Status' if not self.ser: print 'Plotter not available' return None self.ser.write(outstr) print 'device busy' s = [] while True: x = self.ser.read() if x == "\x0d" or not x: break s.append(x) return ''.join(s) except OSError: return None @property def xmin(self): return self.__boundaries[0] @property def ymin(self): return self.__boundaries[1] @property def xmax(self): return self.__boundaries[2] @property def ymax(self): return self.__boundaries[3] @property def center(self): return (self.xmin + self.xmax)/2, (self.ymin + self.ymax)/2 def write(self,programm): self.ser.write(str(programm)) @property def winsize(self): return self.xmax-self.xmin , self.ymax - self.ymin def oob(self, prog): return (prog.xmax > self.xmax or prog.xmin < self.xmin or prog.ymin < self.ymin or prog.ymax > self.ymax) def full(self,prog): arg = min(self.winsize[0]/prog.winsize[0],self.winsize[1]/prog.winsize[1]) print arg return prog*arg def plot(self,prog): if (not self.oob(prog)) and self.ready: self.write(prog) if self.oob(prog): print 'programm out of bound' if not self.ready: print 'device not ready' def centralize(self,prog): return prog-prog.center \ if self.p0incenter else \ prog-(prog.xmin,prog.ymin) @property def ready(self): return bool(self.getoutput('OS;')) plt=Plotter() p=Program() p.parsefile("hpgl/nmk.hpgl") print p.xmin,p.xmax,p.ymin,p.ymax p=p.flip() p=p*(1,-1) p=plt.full(p) p=plt.centralize(p) print 'Programm Größe' p.winsize print 'Program Abmessung' p.xmin,p.xmax,p.ymin,p.ymax print 'Programm Center' p.center print ' Plotter bereit' plt.ready #print str(p) plt.plot(p) print len(p) #print str(p)