# (c) 2014 David Douard # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License (LGPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # for detail see the LICENCE text file. # # FCGear is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with FCGear; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 import itertools from involute import CreateExternalGear, CreateInternalGear, rotate class SVGWireBuilder(object): def __init__(self): self.theta = 0.0 self.pos = None self.svg = [] def move(self, p): p = rotate(p, self.theta) self.svg.append("M %s,%s" % (p[0], p[1])) self.pos = p def line(self, p): p = rotate(p, self.theta) self.svg.append("L %s,%s" % (p[0], p[1])) self.pos = p def arc(self, p, r, sweep): p = rotate(p, self.theta) self.svg.append("A %s,%s 0,0,%s %s,%s" % (r, r, str(sweep), p[0], p[1])) self.pos = p def curve(self, *points): """Add a Bezier curve from self.pos to points[-1] every other points are the control points of the Bezier curve (which will thus be of degree len(points) ) """ assert len(points) == 3 points = [rotate(p, self.theta) for p in points] self.svg.append("C %s,%s %s,%s %s,%s" % tuple(itertools.chain(*points))) self.pos = points[-1] def close(self): self.svg.append("Z") if __name__ == "__main__": from optparse import OptionParser p = OptionParser( usage="usage: %prog [options] [[MODULE] NUMER_OF_TEETH]", description=( "Generates the outline of a metric, involute gear. " "Prints out an SVG path. " "This is mainly a debugging tool to quickly inspect the gear visually. " "For this, online tools like https://yqnn.github.io/svg-path-editor/ are handy. " "Most of the time it's enough to just use the first 20 lines or so, e.g.:\n\t" "%prog -z50 | head -n20 | pbcopy" ), ) p.add_option( "-z", "--numer-of-teeth", help="The number of teeth for the gear.", metavar="NUMER_OF_TEETH", type="int", ) p.add_option( "-m", "--module", help="The metric module, in svg user unit, i.e. unit-less. [default: %default]", metavar="MODULE", type="float", default=1, ) p.add_option( "-p", "--pressure-angle", help="The pressure angle, in degree. [default: %default]", metavar="PRESSURE_ANGLE", type="float", default=20, ) p.add_option( "-i", "--internal", help=( "Generates an internal gear, i.e. the addednum points towards the center " "and the root fillet is at the outside. [default: %default]" ), action="store_true", default=False, ) p.add_option( "-a", "--addendum", help=( "The tooth height above the pitch line, normalized by the MODULE. " "[default: %default]" ), metavar="ADDENDUM_COEFFICIENT", type="float", default=1, ) p.add_option( "-d", "--dedendum", help=( "The tooth height from the root to the pitch line, normalized by the MODULE. " "[default: %default]" ), metavar="DEDENDUM_COEFFICIENT", type="float", default=1.25, ) p.add_option( "-f", "--fillet-radius", help=("The radius of the root fillet, normalized by the MODULE. " "[default: %default]"), metavar="FILLET_RADIUS_COEFFICIENT", type="float", default=0.38, ) opts, args = p.parse_args() errors = [] if len(args) == 1: opts.numer_of_teeth = int(args[0]) if len(args) == 2: opts.module = float(args[0]) opts.numer_of_teeth = int(args[1]) if len(args) > 2: errors.append("Too many arguments.") if opts.numer_of_teeth is None: errors.append("No number of teeth given.") if len(errors) > 0: errors.append("Try --help for more info.") p.error("\n".join(errors)) w = SVGWireBuilder() generator_func = CreateInternalGear if opts.internal else CreateExternalGear generator_func( w, opts.module, opts.numer_of_teeth, opts.pressure_angle, addCoeff=opts.addendum, dedCoeff=opts.dedendum, filletCoeff=opts.fillet_radius, ) for l in w.svg: print(l)