plotter/hpgl_parser.py

changeset 32
59da528bc470
parent 20
de60b63b2275
child 34
022e881b758e
equal deleted inserted replaced
31:c869766e25ff 32:59da528bc470
1 # -*- coding: utf-8 -*-
2
3 import re
4 import numpy
5
6 vsplitter = re.compile('[ ,]')
7 vextractor = re.compile('(?P<value>[^;\n\r\aA-DF-Za-df-z]*?)(?P<terminator>[;\n\r\a]+)', re.S+re.M)
8
9 class HPGLParser(object):
10 def __init__(self, data=None):
11 self.str_terminator = chr(0x03)
12 self.IN()
13 if data:
14 self.parse(data)
15
16 def parse(self, data):
17 self.data = data
18 self.idx = 0
19 self.IN()
20 while self.idx<len(data):
21 while data[self.idx] in [';','\n','\r', '\a', ' ']:
22 self.idx += 1
23 if data[self.idx] == chr(0x03):
24 self.ESC()
25 else:
26 cmd = data[self.idx: self.idx+2]
27 self.idx += 2
28 getattr(self, cmd)()
29 while self.idx<len(data) and data[self.idx] in [';','\n','\r', '\a', ' ']:
30 self.idx += 1
31
32 def user_to_abs(self, pos):
33 """
34 converts a position (x, y) given in user units to absolute
35 units
36 """
37 return pos #TODO
38
39 def extract_value(self, raw=False):
40 m = vextractor.match(self.data[self.idx:])
41 if m:
42 val = m.group("value")
43 self.idx = self.idx + len(val) + len(m.group("terminator"))
44 val = vsplitter.split(val)
45 if not raw:
46 val = [eval(x) for x in val if x.strip()]
47 return val
48 return []
49
50 def extract_string(self):
51 idx2 = self.data.find(self.str_terminator, self.idx)
52 val = self.data[self.idx: idx2]
53 self.idx = idx2+1
54 return val
55
56 def polyline(self, values):
57 if (len(values)%2) == 1:
58 # this is a syntax error in the HPGL data
59 values = values[:-1]
60 values = numpy.array(values).reshape(-1, 2)
61 # TODO use scaling
62 # do plots
63 values = numpy.r_[[self.pos], values] #add self.pos as 1st value
64 if self.plot_mode == 'relative':
65 values = values.cumsum(axis=0)
66 if self.symbol_mode:
67 self.plot_symbols(values[1:])
68 if self.pen_state == "down":
69 self.plot_lines(values)
70 self.pos = values[-1]
71
72 def plot_string(self, s):
73 pass
74
75 def get_window_for_paper(self):
76 return 0,100,0,100
77 def get_scaling_points_for_paper(self):
78 return 0,100,0,100
79
80 # effective plot methods; to be defined in subclasses (backends)
81 def plot_symbols(self, points):
82 pass
83 def plot_lines(self, points):
84 pass
85
86 # HPGL-related methods
87 def ESC(self):
88 #print "ESC"
89 self.idx += 1
90
91 def OE(self):
92 """ Output Error """
93 pass
94
95 def EC(self):
96 """? what's this """
97 values = self.extract_value()
98
99 def OO(self):
100 """idem"""
101 pass
102
103 def OP(self):
104 """idem"""
105 pass
106
107 def VS(self):
108 """idem"""
109 pass
110
111
112 def DF(self):
113 """ Default """
114 self.pen = 0
115 self.pen_width = 1 # 1/300 inch
116 self.pos = 0,0
117 self.char_set = "std"
118 self.plot_mode = 'absolute'
119 self.char_direction = 1,0
120 self.line_type = 0 # 'solid'
121 self.pattern_len = 4 #percentage
122 self.window = self.get_window_for_paper()
123 self.char_size = 0.75, 1.5 #percentages
124 self.symbol_mode = False
125 self.tick_len = 0.5, 0.5 # %
126 self.std_char_set = 0
127 self.alt_char_set = 0
128 self.selected_char_set = 0
129 self.char_slant = 0 # degrees
130 self.scale = None
131 self.str_terminator = chr(0x03)
132 self.chord_ang = 5 #degrees
133 self.fill_type = 'bidirectionnal', 1
134 self.fill_distance = 1 # %
135 self.fill_slant = 0 # degrees
136 self.pen_thickness = 0.3 # mm
137
138 def IN(self):
139 """ Initialize """
140 self.DF()
141 self.pen_state = "up"
142 self.rotation = 0 #degrees
143 self.scaling_points = self.get_scaling_points_for_paper()
144
145 def IP(self):
146 """ Input Scale Point"""
147 values = self.extract_value()
148 if len(values) == 0:
149 self.scaling_points = self.get_scaling_points_for_paper()
150 elif len(values) == 2:
151 p1x, p1y, p2x, p2y = self.scaling_points
152 dx, dy = p2x-p1x, p2y-p1y
153 x, y = values
154 self.scaling = (x, y, x+dx, y+dy)
155 elif len(values) == 4:
156 self.values = tuple(values)
157
158 def SC(self):
159 """ Scale """
160 values = self.extract_value()
161 if len(values) == 4:
162 self.scale = tuple(values)
163 else:
164 self.scale = None
165
166 def IW(self):
167 values = self.extract_value()
168 if len(values) == 0:
169 self.window = self.get_window_for_paper()
170 elif len(value) == 4:
171 self.window = tuple(values)
172
173 def RO(self):
174 values = self.extract_value()
175 if len(values) == 0:
176 self.rotation = 0
177 elif len(values) == 1:
178 self.rotation = values[0]
179
180 def PG(self):
181 pass
182
183 def PU(self):
184 """ Pen Up"""
185 self.pen_state = "up"
186 values = self.extract_value()
187 self.polyline(values)
188
189 def PD(self):
190 """ Pen Down """
191 self.pen_state = "down"
192 values = self.extract_value()
193 self.polyline(values)
194
195 def PA(self):
196 """ Plot Absolute """
197 self.plot_mode = "absolute"
198 values = self.extract_value()
199 self.polyline(values)
200
201 def PR(self):
202 """ Plot Relative """
203 self.plot_mode = "relative"
204 values = self.extract_value()
205 self.polyline(values)
206
207 def AA(self):
208 """ Arc Absolute """
209 values = self.extract_value()
210 if len(values) in [3, 4]:
211 x, y, qc = values[:3]
212 if len(values)==4:
213 qd = values[-1]
214 else:
215 qd = self.chord_ang
216 # TODO : plot arc
217 print "plotting an arc"
218 def AR(self):
219 """ Arc Relative """
220 values = self.extract_value()
221 # TODO
222
223 def CI(self):
224 """ Circle Plot"""
225 values = self.extract_value()
226 # TODO
227
228 def EA(self):
229 """Edge Rectangle Absolute"""
230 values = self.extract_value()
231 # TODO
232
233 def ER(self):
234 """Edge Rectangle Relative"""
235 values = self.extract_value()
236 # TODO
237
238 def EW(self):
239 """ Edge Wedge """
240 values = self.extract_value()
241 # TODO
242
243 def RA(self):
244 """ Fill Rectangle Absolute """
245 values = self.extract_value()
246 # TODO
247
248 def RR(self):
249 """ Fill Rectangle Relative """
250 values = self.extract_value()
251 # TODO
252
253 def WG(self):
254 """ Fill Wedge """
255 values = self.extract_value()
256 # TODO
257
258 def FT(self):
259 """ Fill Type """
260 values = self.extract_value()
261 # TODO
262
263 def LT(self):
264 """ Line Type """
265 values = self.extract_value()
266
267 if len(values)==0:
268 self.line_type = 0 #'solid'
269 else:
270 self.line_type = values[0]
271 if len(values)>1:
272 self.pattern_len = values[1]
273
274 def PW(self):
275 """ Pen Width """
276 values = self.extract_value()
277 if len(values) == 1:
278 self.pen_thickness = values[0]
279
280 def SM(self):
281 """ Symbol Mode """
282 values = self.extract_value()
283 if len(values) == 0:
284 self.symbol_mode = False
285 elif len(values) == 1:
286 self.symbol_mode = values[0]
287
288 def SP(self):
289 """ Select Pen """
290 values = self.extract_value()
291 if len(values) == 1:
292 self.pen = values[0]
293
294 def TL(self):
295 """ Tick Len """
296 values = self.extract_value()
297 # TODO
298
299 def XT(self):
300 """ X-axis Tick """
301 # TODO
302 print "X ticks"
303
304 def YT(self):
305 """ X-axis Tick """
306 # TODO
307 print "Y ticks"
308
309 def PT(self):
310 """ Pen Thickness Select """
311 values = self.extract_value()
312 if len(values) == 0:
313 self.pen_thickness = 0.3
314 elif len(values) == 1:
315 self.pen_thickness = values[0]
316
317 def CS(self):
318 """ Standard Character Set """
319 values = self.extract_value()
320 if len(values) == 0:
321 self.std_char_set = 0
322 elif len(values) == 1:
323 self.std_char_set = values[0]
324
325 def CA(self):
326 """ Alternate Character Set """
327 values = self.extract_value()
328 if len(values) == 0:
329 self.alt_char_set = 0
330 elif len(values) == 1:
331 self.alt_char_set = values[0]
332
333 def SS(self):
334 """ Select Standard Character Set """
335 self.char_set = "std"
336
337 def SA(self):
338 """ Select Alternate Character Set """
339 self.char_set = "alt"
340
341 def DT(self):
342 """ Define Label Terminator """
343 values = self.extract_value(raw=True)
344 if len(values) == 0:
345 self.str_terminator = chr(0x03)
346 elif len(values) == 1:
347 self.str_terminator = values[0]
348
349 def LB(self):
350 """ Character Plot """
351 values = self.extract_string()
352 self.plot_string(values)
353 x, y = self.pos
354 values = values.split('\n')
355 if self.char_size == "absolute":
356 x += len(values[-1]) * self.char_width *1016/2.54
357 y += (len(values)-1) * self.char_height *1016/2.54
358 else:
359 x0, x1, y0, y1 = self.scale
360 dx = x1-x0
361 dy = y1-y0
362 x += len(values[-1]) * self.char_width / 100.0 * dx
363 y += (len(values)-1) * self.char_height / 100.0 * dy
364
365 #print "LB pos[%s] %s -> %s"%(repr(values), self.pos, (x,y))
366 self.pos = [x, y]
367
368 def get_char_size(self):
369 if self.char_size == "absolute":
370 x = self.char_width *1016/2.54
371 y = self.char_height *1016/2.54
372 else:
373 x0, x1, y0, y1 = self.scale
374 dx = x1-x0
375 dy = y1-y0
376 x = self.char_width / 100.0 * dx
377 y = self.char_height / 100.0 * dy
378 return x, y
379
380 def DI(self):
381 """ Absolute Direction """
382 values = self.extract_value()
383 if len(values) == 0:
384 self.char_direction = 1.0, 0.0
385 elif len(values) == 2:
386 self.char_direction = values
387
388 def DR(self):
389 """ Relative Direction """
390 values = self.extract_value()
391 if len(values) == 0:
392 self.char_direction = 1.0, 0.0
393 elif len(values) == 2:
394 # TODO : compute as percentages
395 self.char_direction = values
396
397 def CP(self):
398 """ Character Plot """
399 values = self.extract_value()
400 # TODO
401 if len(values) == 0:
402 values = 0, 1
403 x, y = self.pos
404 if self.char_size == "absolute":
405 x += values[0] * self.char_width *1016/2.54
406 y += values[1] * self.char_height *1016/2.54
407 else:
408 x0, x1, y0, y1 = self.scale
409 dx = x1-x0
410 dy = y1-y0
411 x += values[0] * self.char_width / 100.0 * dx
412 y += values[1] * self.char_height / 100.0 * dy
413 #print "CB pos[%s] %s -> %s"%(repr(values), self.pos, (x,y))
414 self.pos = [x, y]
415
416 def SI(self):
417 """ Set Absolute Character Size """
418 values = self.extract_value()
419 self.char_size = "absolute"
420 if len(values) == 0:
421 self.char_width = 0.1879 # cm
422 self.char_height = 0.2690 # cm
423 elif len(values) == 2:
424 self.char_width, self.char_height = values
425
426 def SR(self):
427 """ Set Relative Character Size """
428 values = self.extract_value()
429 self.char_size = "relative"
430 if len(values) == 0:
431 self.char_width = 0.75 # percentage
432 self.char_height = 1.5 # id
433 elif len(values) == 2:
434 self.char_width, self.char_height = values
435
436 def SL(self):
437 """ Character Slant """
438 values = self.extract_value()
439 # TODO
440
441 def UC(self):
442 """ User Defined Character """
443 values = self.extract_value()
444 # TODO
445
446 if __name__ == '__main__':
447 import sys
448 data = open(sys.argv[1]).read()
449
450 p = HPGLParser(data)
451

mercurial