2 from PIL import Image, ImageDraw, ImageFont |
2 from PIL import Image, ImageDraw, ImageFont |
3 import argparse, sys |
3 import argparse, sys |
4 from data import CYLINDER, PIPES |
4 from data import CYLINDER, PIPES |
5 from config import FONTBASE |
5 from config import FONTBASE |
6 |
6 |
7 SCADSCRIPT = "// Color support only in compile mode (F5)\ninclude <cylindertransport.scad>\n" |
|
8 |
|
9 def offset(r1, r2): |
7 def offset(r1, r2): |
10 return (2*sqrt(r1*r2)) |
8 return (2*sqrt(r1*r2)) |
11 |
9 |
12 def calc_min(r1, r2, space_min): |
10 class CylinderSpacerCalculator: |
13 # stupider annaehreungsversuch, bis sich die beiden Tauchflaschen r1 und r2 nicht mehr beruehren |
11 def __init__(self, cylinders = ["10", "10"], space_min = 10): |
14 for p in PIPES: |
12 self.cylinders = cylinders |
15 i = p[1] / 2 |
13 self.space_min = space_min |
16 if i>r1 or i>r2: |
14 self.font = FONTBASE + "arial.ttf" |
17 print "spacer radius > r1 or r2, abort" |
15 self.scad = "// Color support only in compile mode (F5)\n" +\ |
18 return None |
16 "include <cylindertransport.scad>\n" |
19 x1 = offset(r1, i) |
17 self.circles = [] |
20 x2 = offset(r2, i) |
18 self.spacings = [] |
21 x = (x1 + x2) - (r1+r2) |
19 self.margin = 20 |
22 if x >= space_min: |
|
23 print "%s Pipe (%.1fmm), Cylinder spacing: %imm" % (p[0], p[1], x) |
|
24 return [r1, i, r2, p[0]] |
|
25 return None |
|
26 |
20 |
27 def circ(draw, x, r, txt = "", txtfactor = 1.0): |
21 def calc_min(self, r1, r2): |
28 draw.arc([x-r, 0, x + r, 2 * r], 0, 360, 'white') |
22 # stupider annaehreungsversuch, bis sich die beiden Tauchflaschen r1 und r2 nicht mehr beruehren |
29 if txt != "": |
23 for p in PIPES: |
30 font = ImageFont.truetype(FONTBASE+"arial.ttf", int(24*txtfactor)) |
24 i = p[1] / 2 |
31 tox, toy = draw.textsize(txt, font=font) |
25 if i>r1 or i>r2: |
32 draw.text((x-tox/2, r-toy/2), txt, font=font, fill='#ffffff') |
26 return None |
|
27 x1 = offset(r1, i) |
|
28 x2 = offset(r2, i) |
|
29 x = (x1 + x2) - (r1+r2) |
|
30 if x >= self.space_min: |
|
31 print "%s Pipe (%.1fmm), Cylinder spacing: %imm" % (p[0], p[1], x) |
|
32 return [r1, i, r2, p[0]] |
|
33 return None |
33 |
34 |
|
35 def _circle(self, x, r, txt = "", size = 1.0): |
|
36 self.circles.append([ |
|
37 x, r, txt, size |
|
38 ]) |
34 |
39 |
35 def draw_bottles(draw, args): |
40 def _calculate(self): |
36 global SCADSCRIPT |
41 # first bottle spacer |
37 bottles = args.cylinders |
42 r1 = CYLINDER[self.cylinders[0]][0] / 2 |
|
43 r2 = CYLINDER[self.cylinders[1]][0] / 2 |
|
44 r1, r2, r3, dn = self.calc_min(r1, r2) |
|
45 x = self.margin + r2 # start offset x |
|
46 self._circle(x, r2, dn, 0.5) |
|
47 self.scad += "spacer(%i, %i, %i, %i);\n" % ( |
|
48 x, r2, r3, CYLINDER[self.cylinders[0]][1]) |
|
49 x = x + offset(r2, r3) |
38 |
50 |
39 spacerY1 = 200 |
51 for i in range(0, len(self.cylinders)-1): |
40 spacerY2 = 220 |
52 r1 = CYLINDER[self.cylinders[i]][0] / 2 |
41 # first bottle spacer |
53 r2 = CYLINDER[self.cylinders[i+1]][0] / 2 |
42 r1 = CYLINDER[bottles[0]][0] / 2 |
54 r1, r2, r3, dn = self.calc_min(r1, r2) |
43 r2 = CYLINDER[bottles[1]][0] / 2 |
55 # draw cylinder |
44 x = 20 + r1 # start offset x |
56 self._circle(x, r1, "Tank " + self.cylinders[i]) |
45 r1, r2, r3, dn = calc_min(r1, r2, args.space_min) |
57 self.scad += "tank(%i, %i, %i);\n" % ( |
46 circ(draw, x, r2, dn, 0.5) |
58 x, r1, CYLINDER[self.cylinders[i]][1]) |
47 SCADSCRIPT = SCADSCRIPT + "spacer(%i, %i, %i, %i);\n" % ( |
59 sx1 = x+r1 |
48 x, r2, r3, CYLINDER[bottles[0]][1]) |
60 x = x + offset(r1, r2) |
49 x = x + offset(r2, r3) |
61 # draw right spacer |
|
62 self._circle(x, r2, dn, 0.5) |
|
63 self.scad += "spacer(%i, %i, %i, %i);\n" % ( |
|
64 x, r2, r1, CYLINDER[self.cylinders[i]][1]) |
|
65 x = x + offset(r2, r3) |
|
66 sx2 = x-r3 |
|
67 if i == (len(self.cylinders) - 2): |
|
68 # draw last bottle |
|
69 self._circle(x, r3, "Tank " + self.cylinders[i+1]) |
|
70 self.scad += "tank(%i, %i, %i);\n" % ( |
|
71 x, r3, CYLINDER[self.cylinders[i+1]][1]) |
|
72 x = x + offset(r2, r3) |
50 |
73 |
51 for i in range(0, len(bottles)-1): |
74 self.spacings.append([sx1, sx2]) |
52 r1 = CYLINDER[bottles[i]][0] / 2 |
|
53 r2 = CYLINDER[bottles[i+1]][0] / 2 |
|
54 r1, r2, r3, dn = calc_min(r1, r2, args.space_min) |
|
55 # draw bottle |
|
56 circ(draw, x, r1, "Tank "+bottles[i]) |
|
57 SCADSCRIPT = SCADSCRIPT + "tank(%i, %i, %i);\n" % ( |
|
58 x, r1, CYLINDER[bottles[i]][1]) |
|
59 sx1 = x+r1 |
|
60 x = x + offset(r1, r2) |
|
61 # draw right spacer |
|
62 circ(draw, x, r2, dn, 0.5) |
|
63 SCADSCRIPT = SCADSCRIPT + "spacer(%i, %i, %i, %i);\n" % ( |
|
64 x, r2, r1, CYLINDER[bottles[i]][1]) |
|
65 x = x + offset(r2, r3) |
|
66 sx2 = x-r3 |
|
67 if i == (len(bottles)-2): |
|
68 # draw last bottle |
|
69 circ(draw, x, r3, "Tank "+bottles[i+1]) |
|
70 SCADSCRIPT = SCADSCRIPT + "tank(%i, %i, %i);\n" % ( |
|
71 x, r3, CYLINDER[bottles[i+1]][1]) |
|
72 x = x + offset(r2, r3) |
|
73 # draw the space between bottles |
|
74 draw.line((sx1, spacerY1, sx1, spacerY2), fill='#ffffff') |
|
75 draw.line((sx2, spacerY1, sx2, spacerY2), fill='#ffffff') |
|
76 txt = "%imm" % (sx2-sx1) |
|
77 font = ImageFont.truetype(FONTBASE+"arial.ttf", 12) |
|
78 tox, toy = draw.textsize(txt, font=font) |
|
79 draw.text((sx1+(sx2-sx1)/2-(tox/2), spacerY2+toy/2), txt, font=font, fill='#ffffff') |
|
80 |
75 |
81 # last bottle spacer |
76 # last bottle spacer pipe |
82 circ(draw, x, r2, dn, 0.5) |
77 self._circle(x, r2, dn, 0.5) |
83 SCADSCRIPT = SCADSCRIPT + "spacer(%i, %i, %i, %i);\n" % ( |
78 self.scad += "spacer(%i, %i, %i, %i);\n" % ( |
84 x, r2, r3, CYLINDER[bottles[i+1]][1]) |
79 x, r2, r3, CYLINDER[self.cylinders[i+1]][1]) |
|
80 return int(x + r2 + self.margin) |
85 |
81 |
86 def getimage(args): |
82 def render_image(self): |
87 image = Image.new('1', (1000, 250)) #create new image, 1000x500 pixels, 1 bit per pixel |
83 width = self._calculate() |
88 draw = ImageDraw.Draw(image) |
84 image = Image.new('1', (width, 250)) # create new image |
89 draw_bottles(draw, args) |
85 draw = ImageDraw.Draw(image) |
90 return image |
86 # draw calculated circles |
|
87 for circle in self.circles: |
|
88 x, r, txt, size = circle |
|
89 draw.arc([x - r, 0, x + r, 2 * r], 0, 360, 'white') |
|
90 if txt != "": |
|
91 font = ImageFont.truetype(self.font, int(24 * size)) |
|
92 tox, toy = draw.textsize(txt, font=font) |
|
93 draw.text((x - tox / 2, r - toy / 2), txt, font=font, fill='#ffffff') |
|
94 |
|
95 # draw the spacing between cylinders |
|
96 spacerY1 = 200 |
|
97 spacerY2 = 220 |
|
98 for spacing in self.spacings: |
|
99 sx1, sx2 = spacing |
|
100 draw.line((sx1, spacerY1, sx1, spacerY2), fill='#ffffff') |
|
101 draw.line((sx2, spacerY1, sx2, spacerY2), fill='#ffffff') |
|
102 txt = "%imm" % (sx2 - sx1) |
|
103 font = ImageFont.truetype(FONTBASE+"arial.ttf", 12) |
|
104 tox, toy = draw.textsize(txt, font=font) |
|
105 draw.text((sx1 + (sx2 - sx1) / 2 - tox / 2, |
|
106 spacerY2 + toy / 2), txt, font=font, fill='#ffffff') |
|
107 |
|
108 return image |
91 |
109 |
92 if __name__ == "__main__": |
110 if __name__ == "__main__": |
93 parser = argparse.ArgumentParser(description="Calculate spacer pipes for pressure cylinder transport\n" + |
111 parser = argparse.ArgumentParser(description = \ |
|
112 "Calculate spacer pipes for pressure cylinder transport\n" +\ |
94 "Known cylinder types:\n" + ", ".join(sorted(CYLINDER.keys())) ) |
113 "Known cylinder types:\n" + ", ".join(sorted(CYLINDER.keys())) ) |
95 parser.add_argument('cylinders', metavar='cylinder', type=str, nargs='+', |
114 parser.add_argument('cylinders', metavar = 'cylinder', |
96 help='cylinder types') |
115 type = str, nargs = '+', help = 'cylinder types') |
97 parser.add_argument('--space', dest='space_min', type=int, |
116 parser.add_argument('--space', dest='space_min', |
98 default=10, |
117 type = int, default=10, |
99 help='minimum space between cylinders (mm)') |
118 help='minimum space between cylinders (mm)') |
100 |
119 |
101 args = parser.parse_args() |
120 args = parser.parse_args() |
102 |
121 |
103 for test in args.cylinders: |
122 for test in args.cylinders: |
104 if not test in CYLINDER.keys(): |
123 if not test in CYLINDER.keys(): |
105 print "Cylinder type '%s' is unknown" % test |
124 print "Cylinder type '%s' is unknown" % test |
106 sys.exit(1) |
125 sys.exit(1) |
107 |
126 |
108 image = getimage(args) |
127 obj = CylinderSpacerCalculator( |
|
128 args.cylinders, args.space_min) |
|
129 |
|
130 image = obj.render_image() |
109 image.show() |
131 image.show() |
110 |
132 |
111 print "\n------------ START SCAD SCRIPT ------------" |
133 print "\n------------ START SCAD SCRIPT ------------" |
112 print SCADSCRIPT + "------------ END SCAD SCRIPT ------------" |
134 print obj.scad + "------------ END SCAD SCRIPT ------------" |