Fri, 21 Dec 2007 23:51:36 +0100
added a (very) beginning HPGL parser (with a simplist matplotlib backend)
# -*- coding: utf-8 -*- import re import numpy vsplitter = re.compile('[ ,]') vextractor = re.compile('(?P<value>[^;\n\r\aA-DF-Za-df-z]*?)(?P<terminator>[;\n\r\a]+)', re.S+re.M) class HPGLParser(object): def __init__(self, data): self.data = data self.idx = 0 self.str_terminator = chr(0x03) 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] self.idx += 2 getattr(self, 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 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): print "ESC" self.idx += 1 def OE(self): """ Output Error """ pass def EC(self): """? what's this """ values = self.extract_value() def OO(self): """idem""" pass def OP(self): """idem""" pass def VS(self): """idem""" pass def DF(self): """ Default """ self.pen = 0 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(value) == 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] else: qd = self.chord_ang # 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" def YT(self): """ X-axis Tick """ # TODO print "Y ticks" 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() # TODO 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 #if len(values) == 2: # self.pos = def SI(self): """ Set Absolute Character Size """ values = self.extract_value() self.char_size = "absolute" if len(values) == 0: self.char_width = 0.1879 self.char_height = 0.2690 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 self.char_height = 1.5 elif len(values) == 2: self.char_width, self.char_height = values def SL(self): """ Character Slant """ values = self.extract_value() # TODO def UC(self): """ User Defined Character """ values = self.extract_value() # TODO if __name__ == '__main__': import sys data = open(sys.argv[1]).read() p = HPGLParser(data)