Mon, 03 Apr 2017 04:19:45 +0200
pylint
4 | 1 | """ |
2 | Calculation of spacer pipes for Scuba cylinder transportation | |
3 | 2017 by NeoSoft, mdd | |
4 | Input: see commandline help | |
5 | Output: 2D schematic & 3D OpenSCAD script | |
6 | """ | |
0 | 7 | from math import sqrt |
8 | from PIL import Image, ImageDraw, ImageFont | |
9 | import argparse, sys | |
2 | 10 | from data import CYLINDER, PIPES |
11 | from config import FONTBASE | |
1 | 12 | |
4 | 13 | def offset(r_1, r_2): |
14 | """ | |
15 | Calculate horizontal center offset of two circles | |
16 | so they tangent each other | |
17 | """ | |
18 | return 2 * sqrt(r_1 * r_2) | |
0 | 19 | |
4 | 20 | class CylinderSpacerCalculator(): |
21 | """ | |
22 | Class to calculate transport spacer pipes between | |
23 | Scuba cylinders | |
24 | """ | |
25 | def __init__(self, cylinders, space_min=10): | |
26 | self.cylinders = cylinders | |
27 | self.space_min = space_min | |
28 | self.font = FONTBASE + "arial.ttf" | |
29 | self.scad = "// Color support only in compile mode (F5)\n" +\ | |
30 | "include <cylindertransport.scad>\n" | |
31 | self.circles = [] | |
32 | self.spacings = [] | |
33 | self.margin = 20 | |
0 | 34 | |
4 | 35 | def calc_min(self, r_1, r_2): |
36 | """ | |
37 | stupider annaehreungsversuch, bis sich die beiden | |
38 | Tauchflaschen r_1 und r_2 nicht mehr beruehren | |
39 | Rueckgabe: 3 Zylinderradien und das label der verwendeten Roehre | |
40 | """ | |
41 | for p in PIPES: | |
42 | i = p[1] / 2 | |
43 | x_1 = offset(r_1, i) | |
44 | x_2 = offset(r_2, i) | |
45 | x = (x_1 + x_2) - (r_1 + r_2) | |
46 | if x >= self.space_min: | |
47 | print "%s Pipe (%.1fmm), Cylinder spacing: %imm" % ( | |
48 | p[0], p[1], x) | |
49 | return [r_1, i, r_2, p[0]] | |
50 | print "Abort: no suitable pipe found" | |
51 | sys.exit(1) | |
0 | 52 | |
4 | 53 | def _circle(self, x, r, txt="", size=1.0): |
54 | """ | |
55 | Push the circle definition for later rendering | |
56 | """ | |
57 | self.circles.append([ | |
58 | x, r, txt, size | |
59 | ]) | |
3 | 60 | |
4 | 61 | def _calculate(self): |
62 | """ | |
63 | Calculate all cylinder and spacer circles | |
64 | """ | |
65 | # first bottle spacer | |
66 | r_1 = CYLINDER[self.cylinders[0]][0] / 2 | |
67 | r_2 = CYLINDER[self.cylinders[1]][0] / 2 | |
68 | r_1, r_2, r_3, dn = self.calc_min(r_1, r_2) | |
69 | x = self.margin + r_2 # start offset x | |
70 | self._circle(x, r_2, dn, 0.5) | |
71 | self.scad += "spacer(%i, %i, %i, %i);\n" % ( | |
72 | x, r_2, r_3, CYLINDER[self.cylinders[0]][1]) | |
73 | x = x + offset(r_2, r_3) | |
0 | 74 | |
4 | 75 | for i in range(0, len(self.cylinders)-1): |
76 | r_1 = CYLINDER[self.cylinders[i]][0] / 2 | |
77 | r_2 = CYLINDER[self.cylinders[i+1]][0] / 2 | |
78 | r_1, r_2, r_3, dn = self.calc_min(r_1, r_2) | |
79 | # draw cylinder | |
80 | self._circle(x, r_1, "Tank " + self.cylinders[i]) | |
81 | self.scad += "tank(%i, %i, %i);\n" % ( | |
82 | x, r_1, CYLINDER[self.cylinders[i]][1]) | |
83 | sx1 = x + r_1 | |
84 | x = x + offset(r_1, r_2) | |
85 | # draw right spacer | |
86 | self._circle(x, r_2, dn, 0.5) | |
87 | self.scad += "spacer(%i, %i, %i, %i);\n" % ( | |
88 | x, r_2, r_1, CYLINDER[self.cylinders[i]][1]) | |
89 | x = x + offset(r_2, r_3) | |
90 | sx2 = x - r_3 | |
91 | if i == (len(self.cylinders) - 2): | |
92 | # draw last bottle | |
93 | self._circle(x, r_3, "Tank " + self.cylinders[i + 1]) | |
94 | self.scad += "tank(%i, %i, %i);\n" % ( | |
95 | x, r_3, CYLINDER[self.cylinders[i + 1]][1]) | |
96 | x = x + offset(r_2, r_3) | |
3 | 97 | |
4 | 98 | self.spacings.append([sx1, sx2]) |
99 | ||
100 | # last bottle spacer pipe | |
101 | self._circle(x, r_2, dn, 0.5) | |
102 | self.scad += "spacer(%i, %i, %i, %i);\n" % ( | |
103 | x, r_2, r_3, CYLINDER[self.cylinders[len(self.cylinders)]][1]) | |
104 | return int(x + r_2 + self.margin) | |
3 | 105 | |
4 | 106 | def centertext(self, draw, x, y, txt, size): |
107 | font = ImageFont.truetype(self.font, int(24 * size)) | |
108 | tox, toy = draw.textsize(txt, font=font) | |
109 | draw.text((x - tox / 2, y - toy / 2), \ | |
110 | txt, font=font, fill='#ffffff') | |
0 | 111 | |
4 | 112 | def render_image(self): |
113 | """ | |
114 | Start the calculation and return rendered PIL image object | |
115 | """ | |
116 | width = self._calculate() | |
117 | image = Image.new('1', (width, 250)) # create new image | |
118 | draw = ImageDraw.Draw(image) | |
119 | # draw calculated circles | |
120 | for circle in self.circles: | |
121 | x, r, txt, size = circle | |
122 | draw.arc([x - r, 0, x + r, 2 * r], 0, 360, 'white') | |
123 | if txt != "": | |
124 | self.centertext(draw, x, r, txt, size) | |
0 | 125 | |
4 | 126 | # draw the spacing between cylinders |
127 | spacer_y1 = 200 | |
128 | spacer_y2 = 220 | |
129 | for sx1, sx2 in self.spacings: | |
130 | draw.line((sx1, spacer_y1, sx1, spacer_y2), fill='#ffffff') | |
131 | draw.line((sx2, spacer_y1, sx2, spacer_y2), fill='#ffffff') | |
132 | self.centertext(draw, sx1 + (sx2 - sx1) / 2, \ | |
133 | spacer_y2 + 10, "%imm" % (sx2 - sx1), 0.5) | |
3 | 134 | |
4 | 135 | return image |
0 | 136 | |
137 | if __name__ == "__main__": | |
4 | 138 | parser = argparse.ArgumentParser(description=\ |
139 | "Calculate spacer pipes for pressure cylinder transport\n" +\ | |
140 | "Known cylinder types:\n" + ", ".join(sorted(CYLINDER.keys()))) | |
141 | parser.add_argument('cylinders', metavar='cylinder', \ | |
142 | type=str, nargs='+', help='cylinder types') | |
143 | parser.add_argument('--space', dest='space_min', \ | |
144 | type=int, default=10, \ | |
3 | 145 | help='minimum space between cylinders (mm)') |
0 | 146 | |
4 | 147 | options = parser.parse_args() |
0 | 148 | |
4 | 149 | for test in options.cylinders: |
150 | if not test in CYLINDER.keys(): | |
151 | print "Cylinder type '%s' is unknown" % test | |
152 | sys.exit(1) | |
0 | 153 | |
4 | 154 | worker = CylinderSpacerCalculator( |
155 | options.cylinders, options.space_min) | |
3 | 156 | |
4 | 157 | image = worker.render_image() |
158 | image.show() | |
1 | 159 | |
4 | 160 | print "\n------------ START SCAD SCRIPT ------------" |
161 | print worker.scad + "------------ END SCAD SCRIPT ------------" |