Mon, 03 Apr 2017 03:15:12 +0200
objectoriz0r with separate calculation and rendering
0 | 1 | from math import sqrt |
2 | from PIL import Image, ImageDraw, ImageFont | |
3 | import argparse, sys | |
2 | 4 | from data import CYLINDER, PIPES |
5 | from config import FONTBASE | |
1 | 6 | |
0 | 7 | def offset(r1, r2): |
2 | 8 | return (2*sqrt(r1*r2)) |
0 | 9 | |
3 | 10 | class CylinderSpacerCalculator: |
11 | def __init__(self, cylinders = ["10", "10"], space_min = 10): | |
12 | self.cylinders = cylinders | |
13 | self.space_min = space_min | |
14 | self.font = FONTBASE + "arial.ttf" | |
15 | self.scad = "// Color support only in compile mode (F5)\n" +\ | |
16 | "include <cylindertransport.scad>\n" | |
17 | self.circles = [] | |
18 | self.spacings = [] | |
19 | self.margin = 20 | |
0 | 20 | |
3 | 21 | def calc_min(self, r1, r2): |
22 | # stupider annaehreungsversuch, bis sich die beiden Tauchflaschen r1 und r2 nicht mehr beruehren | |
23 | for p in PIPES: | |
24 | i = p[1] / 2 | |
25 | if i>r1 or i>r2: | |
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 | |
0 | 34 | |
3 | 35 | def _circle(self, x, r, txt = "", size = 1.0): |
36 | self.circles.append([ | |
37 | x, r, txt, size | |
38 | ]) | |
39 | ||
40 | def _calculate(self): | |
41 | # first bottle spacer | |
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) | |
0 | 50 | |
3 | 51 | for i in range(0, len(self.cylinders)-1): |
52 | r1 = CYLINDER[self.cylinders[i]][0] / 2 | |
53 | r2 = CYLINDER[self.cylinders[i+1]][0] / 2 | |
54 | r1, r2, r3, dn = self.calc_min(r1, r2) | |
55 | # draw cylinder | |
56 | self._circle(x, r1, "Tank " + self.cylinders[i]) | |
57 | self.scad += "tank(%i, %i, %i);\n" % ( | |
58 | x, r1, CYLINDER[self.cylinders[i]][1]) | |
59 | sx1 = x+r1 | |
60 | x = x + offset(r1, r2) | |
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]) | |
0 | 65 | x = x + offset(r2, r3) |
3 | 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) | |
73 | ||
74 | self.spacings.append([sx1, sx2]) | |
75 | ||
76 | # last bottle spacer pipe | |
77 | self._circle(x, r2, dn, 0.5) | |
78 | self.scad += "spacer(%i, %i, %i, %i);\n" % ( | |
79 | x, r2, r3, CYLINDER[self.cylinders[i+1]][1]) | |
80 | return int(x + r2 + self.margin) | |
0 | 81 | |
3 | 82 | def render_image(self): |
83 | width = self._calculate() | |
84 | image = Image.new('1', (width, 250)) # create new image | |
85 | draw = ImageDraw.Draw(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') | |
0 | 94 | |
3 | 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 | |
0 | 109 | |
110 | if __name__ == "__main__": | |
3 | 111 | parser = argparse.ArgumentParser(description = \ |
112 | "Calculate spacer pipes for pressure cylinder transport\n" +\ | |
0 | 113 | "Known cylinder types:\n" + ", ".join(sorted(CYLINDER.keys())) ) |
3 | 114 | parser.add_argument('cylinders', metavar = 'cylinder', |
115 | type = str, nargs = '+', help = 'cylinder types') | |
116 | parser.add_argument('--space', dest='space_min', | |
117 | type = int, default=10, | |
118 | help='minimum space between cylinders (mm)') | |
0 | 119 | |
120 | args = parser.parse_args() | |
121 | ||
122 | for test in args.cylinders: | |
123 | if not test in CYLINDER.keys(): | |
124 | print "Cylinder type '%s' is unknown" % test | |
125 | sys.exit(1) | |
126 | ||
3 | 127 | obj = CylinderSpacerCalculator( |
128 | args.cylinders, args.space_min) | |
129 | ||
130 | image = obj.render_image() | |
1 | 131 | image.show() |
132 | ||
133 | print "\n------------ START SCAD SCRIPT ------------" | |
3 | 134 | print obj.scad + "------------ END SCAD SCRIPT ------------" |