#
#gear.py
#Ed Baafi

from math import *
from Numeric import *



#parameters

radius = 1. # radius of inner circle
outer = 1.5 #radius of outer circle
teeth = 16. # number of teeth
space_percent = .20 # space is this percent of space + tooth
top_percent = .3   # top of tooth is this percent of tooth

shaft_radius = .5

#calculate these


radians=2*pi/teeth # number of radians of 1 tooth + space
tooth_percent = 1 -space_percent
tooth_radians = tooth_percent * radians
space_radians = space_percent * radians
top_radians  = top_percent * radians

HUGE = 1e10

def line(x0,y0,x1,y1):
   xpath[-1].append(x0)
   ypath[-1].append(y0)
   xpath[-1].append(x1)
   ypath[-1].append(y1)

def arc(x0,y0,x1,y1,x2,y2):
   N = 100
   r = sqrt((x1-x0)**2 + (y1-y0)**2)

   theta1 = atan((y1-y0)/(x1-x0))

   if ((x1 < x0) & (y1 < y0)) | ((x1 < x0) & (y1 > y0)):
      theta1 = theta1 + pi
   theta2 = atan((y2-y0)/(x2-x0))
   if ((x2 < x0) & (y2 < y0)) | ((x2 < x0) & (y2 > y0)):
      theta2 = theta2 + pi
   for i in range(N):
      theta = theta1 + (theta2-theta1)*i/(N-1.0)
      x = x0 + r*cos(theta)
      y = y0 + r*sin(theta)
      xpath[-1].append(x)
      ypath[-1].append(y)

def circle(radius):

   NumLines = 1000

   increment = 2*pi/NumLines
   theta = 0

   for i in range(NumLines+1):
     xpath[-1].append(radius*cos(theta))
     ypath[-1].append(radius*sin(theta))
     theta = theta + increment





def svgwrite(xpath,ypath,filename):
   xmin = HUGE
   ymin = HUGE
   xmax = -HUGE
   ymax = -HUGE
   for piece in range(len(xpath)):
      for point in range(len(xpath[piece])):
         x = xpath[piece][point]
         y = ypath[piece][point]
         if (x < xmin): xmin = x
         if (x > xmax): xmax = x
         if (y < ymin): ymin = y
         if (y > ymax): ymax = y
   outfile = open(filename,"w")
   outfile.write('<?xml version="1.0" encoding="UTF-8"?>\n')
   outfile.write('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">\n')
   outfile.write('<svg width="%fin" height="%fin" viewBox="%f %f %f %f">\n'\
      %(xmax-xmin,ymax-ymin,xmin,ymin,xmax-xmin,ymax-ymin))
   outfile.write('<g style="stroke:rgb(0,0,0);fill:none">\n')
   for piece in range(len(xpath)):
      outfile.write('<polyline points="')
      for point in range(len(xpath[piece])):
         x = xpath[piece][point]
         y = ypath[piece][point]
         outfile.write('%f,%f '%(x,-y))
      x = xpath[piece][-1]
      y = ypath[piece][-1]
      outfile.write('%f,%f" '%(x,-y))
      outfile.write('style="fill:none"/>\n')
   outfile.write('</g>\n')
   outfile.write('</svg>\n')
   outfile.close()

x = 0
y = 0

xpath = []
ypath = []

def generate_tooth(theta3):

   line(radius*cos(theta3-(tooth_radians/2)), radius*sin(theta3-(tooth_radians/2)),outer*cos(theta3-(top_radians/2)), outer*sin(theta3-(top_radians/2)))
   line(outer*cos(theta3-(top_radians/2)), outer*sin(theta3-(top_radians/2)),outer*cos(theta3+(top_radians/2)), outer*sin(theta3+(top_radians/2)))
   line(outer*cos(theta3+(top_radians/2)), outer*sin(theta3+(top_radians/2)),radius*cos( theta3+(tooth_radians/2) ), radius*sin( theta3+(tooth_radians/2) ))
   arc( x,y, radius*cos( theta3+(tooth_radians/2) ), radius*sin( theta3+(tooth_radians/2) ),radius*cos( theta3+(tooth_radians/2)+space_radians ), radius*sin( theta3+(tooth_radians/2)+space_radians ))


def generate_gear():
   global x,y
   xpath.append([])
   ypath.append([])

   i = 0
   while i<teeth:
      generate_tooth((pi/2)+(i*radians))
      i=i+1



def generate_shaft():
   global x,y
   xpath.append([])
   ypath.append([])

   circle(shaft_radius)



generate_gear()
generate_shaft()

svgwrite(xpath,ypath,"gear.svg")

print "GEAR written to gear.svg"
