Sun, 02 Apr 2017 23:59:00 +0200
cylinder transport spacer calculation
0 | 1 | from math import sqrt |
2 | from PIL import Image, ImageDraw, ImageFont | |
3 | import argparse, sys | |
4 | ||
5 | # pfad zu den TTF files (arial.ttf) | |
6 | FONTBASE = "/usr/share/fonts/truetype/msttcorefonts/" | |
7 | ||
8 | SPACE_MIN = 10 # minimum offset between bottles | |
9 | ||
10 | # Durchmesser, Laenge, Volumen und Gewicht der verfuegbaren Tauchflaschen | |
11 | CYLINDER = { | |
12 | "03" : [100, 515, 3, 4.7], | |
13 | "05" : [140, 466, 5, 5.7], | |
14 | "07" : [140, 605, 7, 8.8], | |
15 | "08" : [171, 490, 8, 10.4], | |
16 | "10" : [171, 595, 10, 12.4], | |
17 | "12S" : [204, 550, 12, 15.4], | |
18 | "12L" : [171, 690, 12, 14.5], | |
19 | "15" : [204, 640, 15, 18.1], | |
20 | } | |
21 | ||
22 | PIPES = [ | |
23 | ["DN8", 13.5], | |
24 | ["DN10", 17.2], | |
25 | ["DN15", 21.3], | |
26 | ["DN20", 26.9], | |
27 | ["DN25", 33.7], | |
28 | ["DN32", 42.4], | |
29 | ["DN40", 48.3], | |
30 | ["DN50", 60.3], | |
31 | ["DN65", 76.1], | |
32 | ["DN80", 88.9], | |
33 | ["DN100", 114.3], | |
34 | ["DN125", 139.7], | |
35 | ["DN150", 168.3], | |
36 | ] | |
37 | ||
38 | ||
39 | ||
40 | def offset(r1, r2): | |
41 | o = (2*sqrt(r1*r2)) | |
42 | #print "offset %i" % o | |
43 | return o | |
44 | ||
45 | def calc_min(r1, r2): | |
46 | # stupider annaehreungsversuch, bis sich die beiden Tauchflaschen r1 und r2 nicht mehr beruehren | |
47 | #print "r1=%.0f r2=%.0f" % (r1, r2) | |
48 | for p in PIPES: | |
49 | i = p[1] / 2 | |
50 | if i>r1 or i>r2: | |
51 | print "spacer radius > r1 or r2, abort" | |
52 | return None | |
53 | x1 = offset(r1, i) | |
54 | x2 = offset(r2, i) | |
55 | x = (x1 + x2) - (r1+r2) | |
56 | if x >= SPACE_MIN: | |
57 | print "%s Pipe (%.1fmm), Cylinder spacing: %imm" % (p[0], p[1], x) | |
58 | return [r1, i, r2, p[0]] | |
59 | return None | |
60 | ||
61 | def circ(draw, x, r, txt = "", txtfactor = 1.0): | |
62 | draw.arc([x-r, 0, x + r, 2 * r], 0, 360, 'white') | |
63 | if txt != "": | |
64 | font = ImageFont.truetype(FONTBASE+"arial.ttf", int(24*txtfactor)) | |
65 | tox, toy = draw.textsize(txt, font=font) | |
66 | draw.text((x-tox/2, r-toy/2), txt, font=font, fill='#ffffff') | |
67 | ||
68 | ||
69 | def draw_bottles(draw, args): | |
70 | bottles = args.cylinders | |
71 | SPACE_MIN = args.space_min | |
72 | ||
73 | spacerY1 = 200 | |
74 | spacerY2 = 220 | |
75 | # first bottle spacer | |
76 | r1 = CYLINDER[bottles[0]][0] / 2 | |
77 | r2 = CYLINDER[bottles[1]][0] / 2 | |
78 | x = 20 + r1 # start offset x | |
79 | r1, r2, r3, dn = calc_min(r1, r2) | |
80 | circ(draw, x, r2, dn, 0.5) | |
81 | x = x + offset(r2, r3) | |
82 | ||
83 | for i in range(0, len(bottles)-1): | |
84 | r1 = CYLINDER[bottles[i]][0] / 2 | |
85 | r2 = CYLINDER[bottles[i+1]][0] / 2 | |
86 | r1, r2, r3, dn = calc_min(r1, r2) | |
87 | # draw bottle | |
88 | circ(draw, x, r1, "Tank "+bottles[i]) | |
89 | sx1 = x+r1 | |
90 | x = x + offset(r1, r2) | |
91 | # draw right spacer | |
92 | circ(draw, x, r2, dn, 0.5) | |
93 | x = x + offset(r2, r3) | |
94 | sx2 = x-r3 | |
95 | if i == (len(bottles)-2): | |
96 | # draw last bottle | |
97 | circ(draw, x, r3, "Tank "+bottles[i+1]) | |
98 | x = x + offset(r2, r3) | |
99 | # draw the space between bottles | |
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), spacerY2+toy/2), txt, font=font, fill='#ffffff') | |
106 | ||
107 | # last bottle spacer | |
108 | circ(draw, x, r2, dn, 0.5) | |
109 | ||
110 | def getimage(args): | |
111 | image = Image.new('1', (1000, 250)) #create new image, 1000x500 pixels, 1 bit per pixel | |
112 | draw = ImageDraw.Draw(image) | |
113 | draw_bottles(draw, args) | |
114 | return image | |
115 | ||
116 | if __name__ == "__main__": | |
117 | parser = argparse.ArgumentParser(description="Calculate spacer pipes for pressure cylinder transport\n" + | |
118 | "Known cylinder types:\n" + ", ".join(sorted(CYLINDER.keys())) ) | |
119 | parser.add_argument('cylinders', metavar='cylinder', type=str, nargs='+', | |
120 | help='cylinder types') | |
121 | parser.add_argument('--space', dest='space_min', type=int, | |
122 | default=SPACE_MIN, | |
123 | help='minimum space between cylinders (mm)') | |
124 | ||
125 | args = parser.parse_args() | |
126 | ||
127 | for test in args.cylinders: | |
128 | if not test in CYLINDER.keys(): | |
129 | print "Cylinder type '%s' is unknown" % test | |
130 | sys.exit(1) | |
131 | ||
132 | image = getimage(args) | |
133 | image.show() |