func Plot(g1, g2 gear.Gear, rotfrac int, fname string) { var width, height int border := 5.0 if g1.Pd > g2.Pd { height = int(g1.GetOutsideDia() + (2 * border)) } else { height = int(g2.GetOutsideDia() + (2 * border)) } width = int((g1.Pd + g2.Pd + g1.GetAddendum() + g2.GetAddendum()) + (2 * border)) centerDist := (g1.Pd + g2.Pd) / 2 cx := int((border + (g1.GetOutsideDia() / 2.0)) * factor) cy := height * factor / 2 var canvas *svg.SVG var f *os.File var err error if fname != "" { f, err = os.Create(fmt.Sprintf("%s.svg", fname)) if err != nil { fmt.Println("Something failed creating file!") } canvas = svg.New(f) } else { canvas = svg.New(os.Stdout) } // Setup canvas so that each drawing unit is 0.01mm. canvas.StartviewUnit(width, height, "mm", 0, 0, width*factor, height*factor) plotGrid(cx, cy, width*factor, height*factor, canvas) rot := 0.0 + ((float64(rotfrac) / 100) * (360 / float64(g1.N))) plotGear(cx, cy, rot, g1, canvas) cx = cx + int(centerDist*factor) if math.Mod(float64(g2.N), 2) == 0 { rot = 180.0 / float64(g2.N) } else { rot = 0.0 } rot -= (float64(rotfrac) / 100) * (360 / float64(g2.N)) plotGear(cx, cy, rot, g2, canvas) // canvas.Text(width *100 /2, height * 100 /2, "Hello, SVG", "text-anchor:middle;font-size:300;fill:black") canvas.End() if f != nil { f.Sync() f.Close() } }
func main() { var Centres float64 // Distance between Centres var Ratio float64 // Required Ratio var DriveTeeth int // Number of teeth on drive gear var DrivenTeeth int // Number of teeth on drive gear var PressureAngle float64 var Backlash float64 var Rotation int // Percent of rotation var FileName string // File name for output. var pCentres = flag.Int("c", 100, "Distance between centres. (Whole mm only)") var pDriveTeeth = flag.Int("n1", 7, "Number of teeth on the first gear") var pDrivenTeeth = flag.Int("n2", 23, "Number of teeth on the second gear") var pPressureAngle = flag.Int("p", 25, "Pressure angle") var pBacklash = flag.String("b", "0.5", "Backlash angle (degrees)") var pFileName = flag.String("o", "", "Output file name, .svg will be appended. stdout if not given") var pRotation = flag.Int("r", 0, "Rotation as percentage of one tooth") flag.Parse() Centres = float64(*pCentres) DriveTeeth = *pDriveTeeth DrivenTeeth = *pDrivenTeeth PressureAngle = float64(*pPressureAngle) var err error Backlash, err = strconv.ParseFloat(*pBacklash, 64) if err != nil { Backlash = 0.0 } Rotation = *pRotation FileName = *pFileName Ratio = float64(DrivenTeeth) / float64(DriveTeeth) var Gear1 gear.Gear Gear1.Pd = (1 / (Ratio + 1)) * Centres * 2 Gear1.N = DriveTeeth Gear1.A = PressureAngle Gear1.B = Backlash var Gear2 gear.Gear Gear2.Pd = (Ratio / (Ratio + 1)) * Centres * 2 Gear2.N = DrivenTeeth Gear2.A = PressureAngle Gear2.B = Backlash plot.Plot(Gear1, Gear2, Rotation, FileName) }
func plotGear(cx int, cy int, rot float64, g gear.Gear, canvas *svg.SVG) { canvas.Gtransform(fmt.Sprintf("translate(%d, %d)", cx, cy)) canvas.Circle(0, 0, int(g.Pd*factor/2), style("dash")) cntrLen := int(g.GetOutsideDia() * factor / 8) canvas.Line(-cntrLen, 0, cntrLen, 0, style("solid")) canvas.Line(0, -cntrLen, 0, cntrLen, style("solid")) canvas.Gtransform(fmt.Sprintf("rotate(%0.3f)", rot)) for i := 0; i < g.N; i++ { canvas.Line(int((math.Cos((360/float64(g.N))*float64(i)*DegToRad) * g.GetRootCircleDia() * factor / 2)), int((math.Sin((360/float64(g.N))*float64(i)*DegToRad) * g.GetRootCircleDia() * factor / 2)), int((math.Cos((360/float64(g.N))*float64(i)*DegToRad) * g.GetOutsideDia() * factor / 2)), int((math.Sin((360/float64(g.N))*float64(i)*DegToRad) * g.GetOutsideDia() * factor / 2)), style("dash")) canvas.Gtransform(fmt.Sprintf("rotate(%f)", 360.0/float64(g.N)*float64(i))) plotInvCurve(g, canvas) canvas.Gend() } canvas.Gend() canvas.Gend() }
func plotInvCurve(g gear.Gear, canvas *svg.SVG) { var px []int var py []int var pyi []int var x, y float64 var r, sr, ang float64 var offsetAng float64 br := g.GetBaseCircleDia() * factor / 2 // Base Radius or := g.GetOutsideDia() * factor / 2 // Outside Radius rr := g.GetRootCircleDia() * factor / 2 // Root Radius pr := g.Pd * factor / 2 // Pitch Circle Radius ang = involuteIntersectAngle(br, pr) x, y = xyLocation(br, ang) offsetAng = math.Atan(y/x) * -1 offsetAng += (math.Pi / (float64(g.N) / 2.0)) / -4.0 if rr > br { sr = rr } else { sr = br } rinc := (or - sr) / 100 for r = sr; r <= or; r += rinc { ang = involuteIntersectAngle(br, r) x, y = xyLocation(br, ang) px = append(px, int(x)) py = append(py, int(y)) pyi = append(pyi, int(y)*-1) } if br > rr { px = append([]int{int(rr)}, px...) py = append([]int{0}, py...) pyi = append([]int{0}, pyi...) } canvas.Gtransform(fmt.Sprintf("rotate(%0.4f)", offsetAng*RadToDeg)) canvas.Polyline(px, py, style("solid")) canvas.Gend() canvas.Gtransform(fmt.Sprintf("rotate(%0.4f)", offsetAng*RadToDeg*-1.0)) canvas.Polyline(px, pyi, style("solid")) canvas.Gend() sx, sy := rotXY(px[len(px)-1], py[len(py)-1], offsetAng) ex, ey := rotXY(px[len(px)-1], pyi[len(pyi)-1], offsetAng*-1.0) canvas.Path(fmt.Sprintf("M%d,%d A%d,%d 0 0 1 %d,%d", sx, sy, int(or), int(or), ex, ey), style("solid")) sx, sy = rotXY(px[0], py[0], -offsetAng) ex, ey = rotXY(px[0], py[0], ((2*math.Pi)/float64(g.N))+offsetAng) canvas.Path(fmt.Sprintf("M%d,%d A%d,%d 0 0 1 %d,%d", sx, sy, int(rr), int(rr), ex, ey), style("solid")) }