Thu, 24 May 2018 23:22:37 +0200
[plotter] flake8
# -*- coding: utf-8 -*- # 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 2 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, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """ Copyright (c) 2007-2018 David Douard (Paris, FRANCE). https://bitbucket.org/dddouard/pygpibtoolkit -- mailto:david.douard@sdfa3.orgx """ import re import numpy vsplitter = re.compile('[ ,]') vextractor = re.compile( r'(?P<value>[^;\n\r\aA-DF-Za-df-z]*?)(?P<terminator>[;\n\r\a]+)', re.S + re.M) class HPGLParser: def __init__(self, data=None): self.str_terminator = chr(0x03) self.IN() if data: self.parse(data) def parse(self, data): self.data = data self.idx = 0 self.IN() while self.idx < len(data): while data[self.idx] in ';\n\r\a ': self.idx += 1 if data[self.idx] == chr(0x03): self.ESC() else: cmd = data[self.idx: self.idx+2].upper() self.idx += 2 try: getattr(self, cmd)() except AttributeError: print("WARNING: received unknown command %s" % repr(cmd)) while self.idx < len(data) and data[self.idx] in ';\n\r\a ': self.idx += 1 def user_to_abs(self, pos): """ converts a position (x, y) given in user units to absolute units """ return pos # TODO def extract_value(self, raw=False): m = vextractor.match(self.data[self.idx:]) if m: val = m.group("value") self.idx = self.idx + len(val) + len(m.group("terminator")) val = vsplitter.split(val) if not raw: val = [eval(x) for x in val if x.strip()] return val return [] def extract_string(self): idx2 = self.data.find(self.str_terminator, self.idx) val = self.data[self.idx: idx2] self.idx = idx2+1 return val def polyline(self, values): if (len(values) % 2) == 1: # this is a syntax error in the HPGL data values = values[:-1] values = numpy.array(values).reshape(-1, 2) # TODO use scaling # do plots values = numpy.r_[[self.pos], values] # add self.pos as 1st value if self.plot_mode == 'relative': values = values.cumsum(axis=0) if self.symbol_mode: self.plot_symbols(values[1:]) if self.pen_state == "down": self.plot_lines(values) self.pos = values[-1] def plot_string(self, s): pass def get_window_for_paper(self): return (0, 100, 0, 100) def get_scaling_points_for_paper(self): return (0, 100, 0, 100) # effective plot methods; to be defined in subclasses (backends) def plot_symbols(self, points): pass def plot_lines(self, points): pass # HPGL-related methods def ESC(self): self.idx += 1 def OE(self): """ Output Error """ pass def EC(self): """? what's this """ # values = self.extract_value() pass def OO(self): """idem""" pass def OP(self): """idem""" pass def VS(self): """idem""" pass def DF(self): """ Default """ self.pen = 0 self.pen_width = 1 # 1/300 inch self.pos = (0, 0) self.char_set = "std" self.plot_mode = 'absolute' self.char_direction = (1, 0) self.line_type = 0 # 'solid' self.pattern_len = 4 # percentage self.window = self.get_window_for_paper() self.char_size = (0.75, 1.5) # percentages self.symbol_mode = False self.tick_len = (0.5, 0.5) # % self.std_char_set = 0 self.alt_char_set = 0 self.selected_char_set = 0 self.char_slant = 0 # degrees self.scale = None self.str_terminator = chr(0x03) self.chord_ang = 5 # degrees self.fill_type = ('bidirectionnal', 1) self.fill_distance = 1 # % self.fill_slant = 0 # degrees self.pen_thickness = 0.3 # mm def IN(self): """ Initialize """ self.DF() self.pen_state = "up" self.rotation = 0 # degrees self.scaling_points = self.get_scaling_points_for_paper() def IP(self): """ Input Scale Point""" values = self.extract_value() if len(values) == 0: self.scaling_points = self.get_scaling_points_for_paper() elif len(values) == 2: p1x, p1y, p2x, p2y = self.scaling_points dx, dy = p2x-p1x, p2y-p1y x, y = values self.scaling = (x, y, x+dx, y+dy) elif len(values) == 4: self.values = tuple(values) def SC(self): """ Scale """ values = self.extract_value() if len(values) == 4: self.scale = tuple(values) else: self.scale = None def IW(self): values = self.extract_value() if len(values) == 0: self.window = self.get_window_for_paper() elif len(values) == 4: self.window = tuple(values) def RO(self): values = self.extract_value() if len(values) == 0: self.rotation = 0 elif len(values) == 1: self.rotation = values[0] def PG(self): pass def PU(self): """ Pen Up""" self.pen_state = "up" values = self.extract_value() self.polyline(values) def PD(self): """ Pen Down """ self.pen_state = "down" values = self.extract_value() self.polyline(values) def PA(self): """ Plot Absolute """ self.plot_mode = "absolute" values = self.extract_value() self.polyline(values) def PR(self): """ Plot Relative """ self.plot_mode = "relative" values = self.extract_value() self.polyline(values) def AA(self): """ Arc Absolute """ values = self.extract_value() if len(values) in [3, 4]: x, y, qc = values[:3] if len(values) == 4: qd = values[-1] # noqa else: qd = self.chord_ang # noqa # TODO : plot arc # print("plotting an arc") def AR(self): """ Arc Relative """ # values = self.extract_value() # TODO def CI(self): """ Circle Plot""" # values = self.extract_value() # TODO def EA(self): """Edge Rectangle Absolute""" # values = self.extract_value() # TODO def ER(self): """Edge Rectangle Relative""" # values = self.extract_value() # TODO def EW(self): """ Edge Wedge """ # values = self.extract_value() # TODO def RA(self): """ Fill Rectangle Absolute """ # values = self.extract_value() # TODO def RR(self): """ Fill Rectangle Relative """ # values = self.extract_value() # TODO def WG(self): """ Fill Wedge """ # values = self.extract_value() # TODO def FT(self): """ Fill Type """ # values = self.extract_value() # TODO def LT(self): """ Line Type """ values = self.extract_value() if len(values) == 0: self.line_type = 0 # 'solid' else: self.line_type = values[0] if len(values) > 1: self.pattern_len = values[1] def PW(self): """ Pen Width """ values = self.extract_value() if len(values) == 1: self.pen_thickness = values[0] def SM(self): """ Symbol Mode """ values = self.extract_value() if len(values) == 0: self.symbol_mode = False elif len(values) == 1: self.symbol_mode = values[0] def SP(self): """ Select Pen """ values = self.extract_value() if len(values) == 1: self.pen = values[0] def TL(self): """ Tick Len """ # values = self.extract_value() # TODO def XT(self): """ X-axis Tick """ # TODO # print("X ticks") pass def YT(self): """ X-axis Tick """ # TODO # print("Y ticks") pass def PT(self): """ Pen Thickness Select """ values = self.extract_value() if len(values) == 0: self.pen_thickness = 0.3 elif len(values) == 1: self.pen_thickness = values[0] def CS(self): """ Standard Character Set """ values = self.extract_value() if len(values) == 0: self.std_char_set = 0 elif len(values) == 1: self.std_char_set = values[0] def CA(self): """ Alternate Character Set """ values = self.extract_value() if len(values) == 0: self.alt_char_set = 0 elif len(values) == 1: self.alt_char_set = values[0] def SS(self): """ Select Standard Character Set """ self.char_set = "std" def SA(self): """ Select Alternate Character Set """ self.char_set = "alt" def DT(self): """ Define Label Terminator """ values = self.extract_value(raw=True) if len(values) == 0: self.str_terminator = chr(0x03) elif len(values) == 1: self.str_terminator = values[0] def LB(self): """ Character Plot """ values = self.extract_string() self.plot_string(values) x, y = self.pos values = values.split('\n') if self.char_size == "absolute": x += len(values[-1]) * self.char_width * 1016 / 2.54 y += (len(values)-1) * self.char_height * 1016 / 2.54 else: x0, x1, y0, y1 = self.scale dx = x1-x0 dy = y1-y0 x += len(values[-1]) * self.char_width / 100.0 * dx y += (len(values)-1) * self.char_height / 100.0 * dy self.pos = [x, y] def get_char_size(self): if self.char_size == "absolute": x = self.char_width * 1016 / 2.54 y = self.char_height * 1016 / 2.54 else: x0, x1, y0, y1 = self.scale dx = x1-x0 dy = y1-y0 x = self.char_width / 100.0 * dx y = self.char_height / 100.0 * dy return x, y def DI(self): """ Absolute Direction """ values = self.extract_value() if len(values) == 0: self.char_direction = (1.0, 0.0) elif len(values) == 2: self.char_direction = values def DR(self): """ Relative Direction """ values = self.extract_value() if len(values) == 0: self.char_direction = (1.0, 0.0) elif len(values) == 2: # TODO : compute as percentages self.char_direction = values def CP(self): """ Character Plot """ values = self.extract_value() # TODO if len(values) == 0: values = 0, 1 x, y = self.pos if self.char_size == "absolute": x += values[0] * self.char_width * 1016 / 2.54 y += values[1] * self.char_height * 1016 / 2.54 else: x0, x1, y0, y1 = self.scale dx = x1-x0 dy = y1-y0 x += values[0] * self.char_width / 100.0 * dx y += values[1] * self.char_height / 100.0 * dy self.pos = [x, y] def SI(self): """ Set Absolute Character Size """ values = self.extract_value() self.char_size = "absolute" if len(values) == 0: self.char_width = 0.1879 # cm self.char_height = 0.2690 # cm elif len(values) == 2: self.char_width, self.char_height = values def SR(self): """ Set Relative Character Size """ values = self.extract_value() self.char_size = "relative" if len(values) == 0: self.char_width = 0.75 # percentage self.char_height = 1.5 # id elif len(values) == 2: self.char_width, self.char_height = values def SL(self): """ Character Slant """ # values = self.extract_value() # TODO pass def UC(self): """ User Defined Character """ # values = self.extract_value() # TODO pass if __name__ == '__main__': import sys data = open(sys.argv[1]).read() p = HPGLParser(data)