Mon, 03 Apr 2017 04:19:45 +0200
pylint
""" Calculation of spacer pipes for Scuba cylinder transportation 2017 by NeoSoft, mdd Input: see commandline help Output: 2D schematic & 3D OpenSCAD script """ from math import sqrt from PIL import Image, ImageDraw, ImageFont import argparse, sys from data import CYLINDER, PIPES from config import FONTBASE def offset(r_1, r_2): """ Calculate horizontal center offset of two circles so they tangent each other """ return 2 * sqrt(r_1 * r_2) class CylinderSpacerCalculator(): """ Class to calculate transport spacer pipes between Scuba cylinders """ def __init__(self, cylinders, space_min=10): self.cylinders = cylinders self.space_min = space_min self.font = FONTBASE + "arial.ttf" self.scad = "// Color support only in compile mode (F5)\n" +\ "include <cylindertransport.scad>\n" self.circles = [] self.spacings = [] self.margin = 20 def calc_min(self, r_1, r_2): """ stupider annaehreungsversuch, bis sich die beiden Tauchflaschen r_1 und r_2 nicht mehr beruehren Rueckgabe: 3 Zylinderradien und das label der verwendeten Roehre """ for p in PIPES: i = p[1] / 2 x_1 = offset(r_1, i) x_2 = offset(r_2, i) x = (x_1 + x_2) - (r_1 + r_2) if x >= self.space_min: print "%s Pipe (%.1fmm), Cylinder spacing: %imm" % ( p[0], p[1], x) return [r_1, i, r_2, p[0]] print "Abort: no suitable pipe found" sys.exit(1) def _circle(self, x, r, txt="", size=1.0): """ Push the circle definition for later rendering """ self.circles.append([ x, r, txt, size ]) def _calculate(self): """ Calculate all cylinder and spacer circles """ # first bottle spacer r_1 = CYLINDER[self.cylinders[0]][0] / 2 r_2 = CYLINDER[self.cylinders[1]][0] / 2 r_1, r_2, r_3, dn = self.calc_min(r_1, r_2) x = self.margin + r_2 # start offset x self._circle(x, r_2, dn, 0.5) self.scad += "spacer(%i, %i, %i, %i);\n" % ( x, r_2, r_3, CYLINDER[self.cylinders[0]][1]) x = x + offset(r_2, r_3) for i in range(0, len(self.cylinders)-1): r_1 = CYLINDER[self.cylinders[i]][0] / 2 r_2 = CYLINDER[self.cylinders[i+1]][0] / 2 r_1, r_2, r_3, dn = self.calc_min(r_1, r_2) # draw cylinder self._circle(x, r_1, "Tank " + self.cylinders[i]) self.scad += "tank(%i, %i, %i);\n" % ( x, r_1, CYLINDER[self.cylinders[i]][1]) sx1 = x + r_1 x = x + offset(r_1, r_2) # draw right spacer self._circle(x, r_2, dn, 0.5) self.scad += "spacer(%i, %i, %i, %i);\n" % ( x, r_2, r_1, CYLINDER[self.cylinders[i]][1]) x = x + offset(r_2, r_3) sx2 = x - r_3 if i == (len(self.cylinders) - 2): # draw last bottle self._circle(x, r_3, "Tank " + self.cylinders[i + 1]) self.scad += "tank(%i, %i, %i);\n" % ( x, r_3, CYLINDER[self.cylinders[i + 1]][1]) x = x + offset(r_2, r_3) self.spacings.append([sx1, sx2]) # last bottle spacer pipe self._circle(x, r_2, dn, 0.5) self.scad += "spacer(%i, %i, %i, %i);\n" % ( x, r_2, r_3, CYLINDER[self.cylinders[len(self.cylinders)]][1]) return int(x + r_2 + self.margin) def centertext(self, draw, x, y, txt, size): font = ImageFont.truetype(self.font, int(24 * size)) tox, toy = draw.textsize(txt, font=font) draw.text((x - tox / 2, y - toy / 2), \ txt, font=font, fill='#ffffff') def render_image(self): """ Start the calculation and return rendered PIL image object """ width = self._calculate() image = Image.new('1', (width, 250)) # create new image draw = ImageDraw.Draw(image) # draw calculated circles for circle in self.circles: x, r, txt, size = circle draw.arc([x - r, 0, x + r, 2 * r], 0, 360, 'white') if txt != "": self.centertext(draw, x, r, txt, size) # draw the spacing between cylinders spacer_y1 = 200 spacer_y2 = 220 for sx1, sx2 in self.spacings: draw.line((sx1, spacer_y1, sx1, spacer_y2), fill='#ffffff') draw.line((sx2, spacer_y1, sx2, spacer_y2), fill='#ffffff') self.centertext(draw, sx1 + (sx2 - sx1) / 2, \ spacer_y2 + 10, "%imm" % (sx2 - sx1), 0.5) return image if __name__ == "__main__": parser = argparse.ArgumentParser(description=\ "Calculate spacer pipes for pressure cylinder transport\n" +\ "Known cylinder types:\n" + ", ".join(sorted(CYLINDER.keys()))) parser.add_argument('cylinders', metavar='cylinder', \ type=str, nargs='+', help='cylinder types') parser.add_argument('--space', dest='space_min', \ type=int, default=10, \ help='minimum space between cylinders (mm)') options = parser.parse_args() for test in options.cylinders: if not test in CYLINDER.keys(): print "Cylinder type '%s' is unknown" % test sys.exit(1) worker = CylinderSpacerCalculator( options.cylinders, options.space_min) image = worker.render_image() image.show() print "\n------------ START SCAD SCRIPT ------------" print worker.scad + "------------ END SCAD SCRIPT ------------"