added a (very) beginning HPGL parser (with a simplist matplotlib backend)

Fri, 21 Dec 2007 23:51:36 +0100

author
David Douard <david.douard@logilab.fr>
date
Fri, 21 Dec 2007 23:51:36 +0100
changeset 18
c691b040e8c9
parent 17
fb8aa055f6e4
child 19
42af82fdb8bb

added a (very) beginning HPGL parser (with a simplist matplotlib backend)

hpgl_mpl.py file | annotate | diff | comparison | revisions
hpgl_parser.py file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hpgl_mpl.py	Fri Dec 21 23:51:36 2007 +0100
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+import numpy
+import pylab
+
+from hpgl_parser import HPGLParser
+
+class HPGLmplPlotter(HPGLParser):
+    pens = "krbgcmyw"
+    lines = ['-', ':', '--', '-.', '.', '-', '-', '-']
+    def __init__(self, data):        
+        super(HPGLmplPlotter, self).__init__(data)
+        pylab.show()
+        
+    def plot_symbols(self, points):
+        x, y = points.T
+        pylab.plot(x, y, 'o')
+
+    def plot_lines(self, points):
+        x, y = points.T
+        pylab.plot(x, y, self.pens[self.pen]+self.lines[self.line_type])
+        
+if __name__ == "__main__":
+    import sys
+    data = open(sys.argv[1]).read()
+    HPGLmplPlotter(data)
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hpgl_parser.py	Fri Dec 21 23:51:36 2007 +0100
@@ -0,0 +1,408 @@
+# -*- 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)
+    

mercurial