1 | #!/usr/bin/python3
|
2 |
|
3 | import svgwrite #muss man installieren
|
4 | import string
|
5 |
|
6 | infilename = 'lesbar.txt'
|
7 | outfilename = 'bild.svg'
|
8 |
|
9 | # hides the ugliness of svgwrite (inverted y)
|
10 | class SvgSheet:
|
11 | def __init__(self, filename):
|
12 | self.xmin=-100
|
13 | self.xmax=1800
|
14 | self.ymin=-100
|
15 | self.ymax=800
|
16 | worldwidth=self.xmax-self.xmin
|
17 | worldheight=self.ymax-self.ymin
|
18 | paperwidth=15 #cm
|
19 | paperheight=10 #cm
|
20 | paperdims=("%fcm" % paperwidth, "%fcm" % paperheight)
|
21 | self.dwg = svgwrite.Drawing(filename=filename, debug=True, size = paperdims)
|
22 | self.dwg.viewbox(minx=self.xmin-1, miny=self.ymin-1, width=worldwidth+2, height=worldheight+2)
|
23 |
|
24 | def w2g(self, xy):
|
25 | return (xy[0], self.ymax -xy[1])
|
26 |
|
27 | def save_image(self):
|
28 | self.dwg.save()
|
29 |
|
30 | def line(self, a, b, color='gray', lw='0.5mm'):
|
31 | self.dwg.add(self.dwg.line(self.w2g(a), self.w2g(b), stroke=color, fill='none', stroke_width=lw, stroke_linecap="round") )
|
32 |
|
33 | def draw_text(self, p, text, color='orange'):
|
34 | self.dwg.add(self.dwg.text(text, insert=self.w2g(p), font_family="Courier New", font_size="28pt", fill=color))
|
35 |
|
36 | #helper to save typing
|
37 | def coords(params):
|
38 | return int(params[0]), int(params[1])
|
39 |
|
40 | class PlotParser:
|
41 | def __init__(self, painter):
|
42 | self.painter = painter
|
43 | # internal state:
|
44 | self.cursor = (0, 0)
|
45 | self.color = 'black'
|
46 | # map command names to functions:
|
47 | self.commands = dict()
|
48 | self.commands['SP'] = self.select_pen
|
49 | self.commands['DA'] = self.draw_absolute
|
50 | self.commands['MA'] = self.move_absolute
|
51 | self.commands['MR'] = self.move_relative
|
52 | self.commands['DR'] = self.draw_relative
|
53 | self.commands['LA'] = self.label
|
54 | self.commands['AX'] = self.axis # halb falsch
|
55 | #so sieht das bild halbwegs gut aus, die wahrheit ist sicher komplizierter:
|
56 | self.commands['OR'] = self.origin # unfug
|
57 | self.commands['HO'] = self.origin # horizontal_origin #unfug
|
58 |
|
59 | # internal functions for the plot commands
|
60 | def move_relative(self, params):
|
61 | dx, dy = coords(params)
|
62 | self.cursor = (self.cursor[0] + dx, self.cursor[1] + dy)
|
63 |
|
64 | def label(self, params):
|
65 | text = params[0]
|
66 | self.painter.draw_text(self.cursor, text, self.color)
|
67 |
|
68 | def move_absolute(self, params):
|
69 | x, y = coords(params)
|
70 | self.cursor =(x, y)
|
71 |
|
72 | def draw_absolute(self, params):
|
73 | x, y = coords(params)
|
74 | self.painter.line(self.cursor, (x, y), self.color)
|
75 | self.cursor = (x, y)
|
76 |
|
77 | def draw_relative(self, params):
|
78 | dx, dy = coords(params)
|
79 | x = self.cursor[0] + dx
|
80 | y = self.cursor[1] + dy
|
81 | self.painter.line(self.cursor, (x, y), self.color)
|
82 | self.cursor =(x, y)
|
83 |
|
84 | def origin(self, params):
|
85 | self.cursor = (0, 0)
|
86 |
|
87 | def horizontal_origin(self, params):
|
88 | self.cursor = (0, self.cursor[1])
|
89 |
|
90 |
|
91 | #AX2,890,10,0,0,250,20,1
|
92 | #AX3,1500,7,0,0,7000,20,0
|
93 | #AX2,890,7,0,0,140,-20,1
|
94 |
|
95 | def axis(self, params): #haesslich und falsch
|
96 | length = int(params[1])
|
97 | partitions = int(params[2]) # abzahl der ticks. das kommt ganz gut hin und gibt mit
|
98 | max_val = int(params[5])
|
99 | tick_offs = int(params[6])
|
100 | direction = int(params[7])
|
101 | x = self.cursor[0]
|
102 | y = self.cursor[1]
|
103 | if direction == 1: #up
|
104 | y = y + length
|
105 | elif direction == 0: #right
|
106 | x = x + length
|
107 | else:
|
108 | return
|
109 | value_step = max_val/partitions
|
110 | self.painter.line(self.cursor, (x, y), self.color)
|
111 | self.painter.draw_text((x, y), str(max_val), self.color)
|
112 | #ticks:
|
113 | if direction == 1: #up
|
114 | i = 0
|
115 | while i <= partitions:
|
116 | ty = self.cursor[1] + i/partitions * (y - self.cursor[1])
|
117 | self.painter.line((x + tick_offs, ty), (x, ty), self.color)
|
118 | self.painter.draw_text((x, ty), str(int(i/partitions * max_val)), self.color)
|
119 | i = i + 1
|
120 | elif direction == 0: #right
|
121 | i = 0
|
122 | while i <= partitions:
|
123 | tx = self.cursor[0] + i/partitions * (x - self.cursor[0])
|
124 | self.painter.line((tx, y + tick_offs), (tx, y), self.color)
|
125 | self.painter.draw_text((tx, y), str(int(i/partitions * max_val)), self.color)
|
126 | i = i + 1
|
127 | self.cursor = (x,y)
|
128 |
|
129 | def select_pen(self, params):
|
130 | pen_num = int(params[0])
|
131 | colors = {1: 'blue', 2: 'red', 3: 'black', 4: 'green'}
|
132 | self.color = colors[pen_num]
|
133 |
|
134 | def unknown(self, command, params):
|
135 | print("unknown command %s(%s)" %(command, ','.join(params)))
|
136 |
|
137 | def interpret(self, s):
|
138 | if len(s) < 2:
|
139 | print('ignoring "%s"' % s)
|
140 | return
|
141 | command = s[0:2]
|
142 | params = s[2:].split(',')
|
143 | if command in self.commands:
|
144 | self.commands[command](params)
|
145 | else:
|
146 | self.unknown(command, params)
|
147 |
|
148 | def finish(self):
|
149 | self.painter.save_image()
|
150 |
|
151 |
|
152 | if __name__ == '__main__':
|
153 | paper = SvgSheet(outfilename)
|
154 | printer = PlotParser(paper)
|
155 |
|
156 | infile = open(infilename, 'r')
|
157 |
|
158 | #nur die zeilen ab der zeile mit GRC
|
159 | graphics_begun = False
|
160 | for li in infile.readlines():
|
161 | line = ''.join(filter(lambda x: x in string.printable, li.strip())) # ugly: remove nonprintable chars
|
162 | if not graphics_begun:
|
163 | if 'GRC' in line:
|
164 | graphics_begun = True
|
165 | if graphics_begun:
|
166 | printer.interpret(line)
|
167 | printer.finish()
|