/// <summary> /// Calculate the contact ratio for two gears. The gears must be /// compatible from a meshing point of view (same module, same /// pressure angle). The contact ratio is the average number of teeth /// in contact with each other on the pressure-bearing faces as /// the gears are rotating. Ideally this should be > 1.1, but the /// absolute minimum is 1 for the gears to not 'click' as they turn. /// Note that this is the ideal figure, valid for no backlash, no /// profile offset, and no undercut. It is the theoretical maximum /// value that is never achieved! /// </summary> /// <param name="g1">The first gear being meshed</param> /// <param name="g2">The second gear being meshed</param> /// <returns>The contact ratio</returns> public static double IdealContactRatio(GearParameters g1, GearParameters g2) { if (g1 == null || !g1.CanMeshWith(g2)) { throw new ArgumentException("Gears have differing modules or pressure angles"); } double gear1 = 0.5 * RootDiffOfSquares (g1.PitchCircleDiameter + 2 * g1.Module, g1.BaseCircleDiameter); double gear2 = 0.5 * RootDiffOfSquares (g2.PitchCircleDiameter + 2 * g2.Module, g2.BaseCircleDiameter); return((gear1 + gear2 - Math.Sin(g1.PressureAngle) * (g1.PitchCircleDiameter + g2.PitchCircleDiameter) / 2) / g1.BaseCirclePitch); }
/// <summary> /// Given we are meshed with another gear where this and /// the other gear might have a profile shift, calculate /// the contact length for the two gears /// </summary> /// <param name="meshedGear">The gear with which we are /// meshed</param> /// <returns>The length of the path along which the two /// gears are in contact before breaking apart</returns> public double ContactDistanceWithGear(GearParameters meshedGear) { if (!CanMeshWith(meshedGear)) { Information = "Gears have differing modules or pressure angles"; return(0); } double distanceBetweenCentres = PitchCircleDiameter / 2 + meshedGear.PitchCircleDiameter / 2 + Module * (ProfileShift + meshedGear.ProfileShift); double distToPitchPoint = distanceBetweenCentres * BaseCircleDiameter / (BaseCircleDiameter + meshedGear.BaseCircleDiameter); double meshedDistToPitchPoint = distanceBetweenCentres - distToPitchPoint; double contactLength = Math.Sqrt(Involutes.DiffOfSquares(distToPitchPoint, BaseCircleDiameter / 2)) - Math.Sqrt(SquaredUndercutRadius - Involutes.Square(BaseCircleDiameter / 2)); double meshedContactLength = Math.Sqrt(Involutes.DiffOfSquares(meshedDistToPitchPoint, meshedGear.BaseCircleDiameter / 2)) - Math.Sqrt(meshedGear.SquaredUndercutRadius - Involutes.Square(meshedGear.BaseCircleDiameter / 2)); return(contactLength + meshedContactLength); }
/// <summary> /// Calculate the sequence of cutout point sequences that make /// the spokes in the gear. Used to try and reduce the inertia /// of larger gears. /// </summary> /// <param name="spokes">The number of spokes to put between /// the gear hub and the teeth-bearing perimeter</param> /// <returns>The point lists that each make up the /// outline of the cutouts</returns> private List <List <PointF> > CalculateCutouts(int spokes) { List <List <PointF> > cutouts = new List <List <PointF> >(); if (spokes < 3) { return(cutouts); } // Set some design constants double cornerRadius = Gear.Module; double spokeThickness = 2.0 * Gear.Module; double minHubDiameter = 8 * Gear.Module; // Calculate the minimum hub diameter for a given number of // spokes, a specified spoke thickness and corner radius. double hubDiameter = (spokeThickness + 2 * cornerRadius) / Math.Sin(Math.PI / spokes) - cornerRadius; if (hubDiameter < minHubDiameter) { hubDiameter = minHubDiameter; } // Calculate the corner at the outer end of one side of a spoke. // For this reference spoke we assume the spoke runs along the // positive X axis. We shall rotate it for other spokes. double rimDiameter = Gear.InnerDiameter - 2.0 * spokeThickness; if (rimDiameter < hubDiameter + 4 * cornerRadius) { return(cutouts); } double cornerCentreY = spokeThickness / 2 + cornerRadius; double rimCornerCentreX = Math.Sqrt (Involutes.DiffOfSquares(rimDiameter / 2 - cornerRadius, cornerCentreY)); PointF rimCornerCentre = Involutes.CreatePt(rimCornerCentreX, cornerCentreY); double angleAtRim = Math.Atan2(cornerCentreY, rimCornerCentreX); IEnumerable <PointF> outerCorner = Involutes.CirclePoints (-Math.PI / 2, angleAtRim, Involutes.AngleStep, cornerRadius, rimCornerCentre); // Calculate the corner at the inner end of a spoke. //double hubCornerCentreX = Math.Sqrt(Square(hubDiameter / 2 + cornerRadius) // - Square(cornerCentreY)); double hubCornerCentreX = Math.Sqrt (Involutes.DiffOfSquares(hubDiameter / 2 + cornerRadius, cornerCentreY)); PointF hubCornerCentre = Involutes.CreatePt(hubCornerCentreX, cornerCentreY); double angleAtHub = Math.Atan2(cornerCentreY, hubCornerCentreX); IEnumerable <PointF> innerCorner = Involutes.CirclePoints (Math.PI + angleAtHub, 3.0 * Math.PI / 2, Involutes.AngleStep, cornerRadius, hubCornerCentre); // Calculate the outer rim circle segment IEnumerable <PointF> outerRimSegment = Involutes.CirclePoints (angleAtRim, 2 * Math.PI / spokes - angleAtRim, Involutes.AngleStep, rimDiameter / 2); // Calculate the hub circle segment IEnumerable <PointF> hubSegment = Involutes.CirclePoints (angleAtHub, 2 * Math.PI / spokes - angleAtHub, Involutes.AngleStep, hubDiameter / 2); // Calculate the far side of the cutout. Reflect the inner spoke // across the X axis, and reverse its points. Then rotate it round the gear // by the angle between adjacent spokes. This gives us the correct // list of points. IEnumerable <PointF> nearSide = innerCorner.Concat(outerCorner); IEnumerable <PointF> farSide = GearParameters.ReflectY(nearSide) .Select(p => Involutes.RotateAboutOrigin(2 * Math.PI / spokes, p)) .Reverse(); // Now create the lists of points for each of the cut outs List <PointF> cutout = new List <PointF>(); cutout.AddRange(nearSide); cutout.AddRange(outerRimSegment); cutout.AddRange(farSide); cutout.AddRange(hubSegment.Reverse()); cutout = Involutes.LinearReduction(cutout, (float)Gear.MaxError); cutouts.Add(cutout); for (int i = 1; i < spokes; i++) { cutouts.Add(new List <PointF>(cutout.Select (p => Involutes.RotateAboutOrigin(2 * Math.PI * i / spokes, p)))); } return(cutouts); }
/// <summary> /// Contact ratio between two gears, allowing /// also for possible profile shift. Contact /// ratio is defined as the average number of /// teeth in contact between two gears as they /// rotate. If this is less than 1.0, there are /// times at which no teeth are meshing on the /// involute surfaces and the gears will /// vibrate or lock up. /// </summary> /// <param name="meshedGear">The other gear we /// are meshing with</param> /// <returns>The contact ratio. Must be greater /// than one for gears to mesh correctly.</returns> public double ContactRatioWith(GearParameters meshedGear) => ContactDistanceWithGear(meshedGear) / BaseCirclePitch;
/// <summary> /// Check that the two gears are compatible for meshing /// </summary> /// <param name="meshedGear">The other gear with which /// we are trying to mesh</param> /// <returns>True if the gears are compatible</returns> public bool CanMeshWith(GearParameters meshedGear) => meshedGear != null && PressureAngle == meshedGear.PressureAngle && Module == meshedGear.Module;