Exemplo n.º 1
0
        private PointF PointAtAngle(double angle)
        {
            double radius = InnerDiameter / 2
                            + (PitchCircleDiameter - InnerDiameter) / 2
                            * angle / ToothAngle;

            return(Involutes.CreatePt(radius * Math.Cos(angle),
                                      radius * Math.Sin(angle)));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Create a hexagonal key shape
        /// around the inlay so that
        /// two gears can be married on
        /// the same centres correctly
        /// </summary>
        /// <returns>The list of points
        /// corresponding to the hex key</returns>

        private List <PointF> CalculateHexKey()
        {
            // Generate the points for one sixth of the key
            double ctrToFace = KeyWidth / 2;
            PointF cornerCtr = Involutes.CreatePt(
                ctrToFace - Gear.CutDiameter / 2,
                (ctrToFace - Gear.CutDiameter / 2) / Math.Sqrt(3.0));
            List <PointF> firstSegment = new List <PointF>
            {
                Involutes.CreatePt(ctrToFace, 0),
                Involutes.CreatePt(ctrToFace, cornerCtr.Y)
            };

            firstSegment.AddRange(
                Involutes.CirclePoints(0, Math.PI / 3, Involutes.AngleStep,
                                       Gear.CutDiameter / 2, cornerCtr));
            firstSegment.Add(Involutes.CreatePt(ctrToFace / 2, Math.Sin(Math.PI / 3) * ctrToFace));
            firstSegment = Involutes.LinearReduction(firstSegment, (float)Gear.MaxError);
            return(Enumerable
                   .Range(0, 6)
                   .Select(i => Involutes.RotateAboutOrigin(i * Math.PI / 3.0, firstSegment))
                   .SelectMany(ep => ep).ToList());
        }
        private void CalculatePoints()
        {
            // Unrotated tooth tip is on the X axis

            ToothTip = Involutes.CreatePt(PitchCircleDiameter / 2, 0);

            // Navigate down the slope of the tooth face

            FaceEnd = Involutes.CreatePt(
                PitchCircleDiameter / 2 - ToothFaceLength * Math.Cos(UndercutAngle),
                -ToothFaceLength * Math.Sin(UndercutAngle));

            // Now find the centre of the undercut circle

            UnderCutCentre = Involutes.CreatePt
                                 (FaceEnd.X - CutDiameter * Math.Sin(UndercutAngle) / 2,
                                 FaceEnd.Y + CutDiameter * Math.Cos(UndercutAngle) / 2);

            // Find the coordinates of the back tip corner of
            // the next tooth in an anticlockwise direction

            BackTip = Involutes.CreatePt(ToothTip.X * Math.Cos(GapAngle),
                                         ToothTip.X * Math.Sin(GapAngle));

            // Find the coordinates of the tangent to the
            // undercut circle of a line drawn from the
            // back of the tooth tip

            double tipToEndAngle =
                Math.Asin(CutDiameter / (2 * Involutes.DistanceBetween(BackTip, UnderCutCentre)));
            double tiptoCtrAngle =
                Math.Atan2(BackTip.Y - UnderCutCentre.Y, BackTip.X - UnderCutCentre.X);

            BackAngle =
                tiptoCtrAngle + Math.PI / 2 - tipToEndAngle;
            OneToothProfile = ComputeOnePitch();
        }
Exemplo n.º 4
0
        private (List <PointF> outer, List <PointF> inner) CalculatePoints()
        {
            // Calculate the inside radius of one end of a link,
            // the two distances for the unequal faces of the
            // polygon that is the profile for the curvature of
            // the chiin links around the sprocket, and the angle
            // between two adjacent links in the chain

            double r = OuterLinkWidth / 2 - WireThickness;
            double a = InnerLinkLength + 2 * r;
            double b = InnerLinkLength - 2 * r;
            double C = Math.PI * (ToothCount - 1) / (double)ToothCount;

            // Use the cosine rule to find the distance between
            // adjacent pairs of links

            double lSquared = Sqr(a);

            lSquared += Sqr(b);
            lSquared -= 2 * a * b * Math.Cos(C);
            double l = Math.Sqrt(lSquared);

            // Find the other two angles, A and B at the other two
            // corners of the same triangle

            // double A = Math.Acos((lSquared + a * a - b * b) / (2 * l * a));
            // double B = Math.PI - A - C;

            // Now compute the radius from the centre of the
            // sprocket to one end of the line between adjacent
            // pairs of links

            radius = l / (2 * Math.Sin(Math.PI / ToothCount));

            // We shall set the origin at the centre of the sprocket. The
            // point in the middle of a link that is parallel to the
            // plane of the sprocket lies on the X axis, the link being
            // parallel to the Y axis. T is the centre of the semicircle
            // formed by one end of the link

            PointF t = Involutes.CreatePt(
                Involutes.RootDiffOfSquares(radius, b / 2), b / 2);

            // C is the centre of the wire for the next link, lying on a
            // line from T in the direction of the 3rd link

            double sinTooth = Math.Sin(Math.PI / ToothCount);
            double cosTooth = Math.Cos(Math.PI / ToothCount);

            PointF c = Involutes.CreatePt(
                t.X - (r - WireThickness / 2) * sinTooth,
                t.Y + (r - WireThickness / 2) * cosTooth);

            // U is the point on the second link parallel to the X
            // axis, closest to the centre of the first link.
            // V is the point on the second link just past its
            // curvature due to the wire thickness, where it
            // becomes parallel to the diagonal face of the sprocket
            // beyond the first link.

            PointF u = Involutes.CreatePt(c.X, c.Y - WireThickness / 2);
            double arcAngle;
            double arcRadius = CutDiameter / 2; // Assume cutter bigger than wire
            PointF convexCtr;

            // Find length to mid point of face on which
            // perpendicular link lies

            double oz = Involutes
                        .RootDiffOfSquares(radius, a / 2) - WireThickness / 2;
            PointF z = Involutes.CreatePt(oz * cosTooth, oz * sinTooth);

            if (WireThickness >= CutDiameter)
            {
                arcRadius = WireThickness / 2;
                // v = Involutes.CreatePt(
                //    c.X - arcRadius * cosTooth,
                //    c.Y - arcRadius * sinTooth);
                arcAngle  = Math.PI * (0.5 - 1.0 / ToothCount);
                convexCtr = c;
            }
            else
            {
                // Coordinate of cutter centre when cutting corner
                // between parallel and perpendicular links

                convexCtr = Involutes
                            .CreatePt(u.X, u.Y + arcRadius);

                // Find the distance from the cutter centre to the sloping face

                double cPerp = u.X * cosTooth - oz + sinTooth * (u.Y + arcRadius);

                // Find the angle from the perpendicular to the intersection point

                arcAngle = Math.Acos(cPerp / arcRadius)
                           + Math.PI / 2 - Math.PI / ToothCount;
            }

            // Now plot one chain link worth of profile

            List <PointF> points = new()
            {
                Involutes.CreatePt(t.X + OuterLinkWidth / 2, 0)
            };
            PointF cUpper = Involutes.CreatePt(t.X, u.Y - OuterLinkWidth / 2);

            points.AddRange(Involutes.CirclePoints(
                                0, Math.PI / 2, Math.PI / 180, OuterLinkWidth / 2, cUpper));
            points.AddRange(Involutes.CirclePoints(
                                1.5 * Math.PI - arcAngle, 1.5 * Math.PI, Math.PI / 180, arcRadius, convexCtr)
                            .Reverse());
            points.Add(z);

            // Now calculate the recess profile

            double grooveStartAngle = Math.Acos(WireThickness / OuterLinkWidth);

            grooveStartAngle = Math.PI * (1.0 + ToothCount) / ToothCount
                               - grooveStartAngle;

            PointF        bt           = Involutes.CreatePt(t.X - Backlash * sinTooth, t.Y + Backlash * cosTooth);
            List <PointF> groovePoints = new();

            InnerDiameter = 2 * t.X - OuterLinkWidth;
            Module        = InnerDiameter / ToothCount;
            groovePoints.Add(Involutes.CreatePt(InnerDiameter / 2 - Backlash * sinTooth, 0));
            groovePoints.AddRange(Involutes.CirclePoints(
                                      grooveStartAngle, Math.PI, Math.PI / 180, OuterLinkWidth / 2, bt)
                                  .Reverse());
            groovePoints.Add(z);
            return(points, groovePoints);
        }
Exemplo n.º 5
0
        /// <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);
        }
Exemplo n.º 6
0
        private void CalculatePoints()
        {
            List <PointF> points       = new List <PointF>();
            double        innerRadius  = InnerDiameter / 2;
            double        cutterRadius = CutDiameter / 2;

            // Calculate the cutter centre for the tooth
            // of the ratchet gear at the innermost end

            double m            = -ToothDepth / (innerRadius * ToothAngle);
            double xs           = Math.Sqrt(cutterRadius * cutterRadius / (1 + m * m));
            double ys           = m * xs;
            PointF cutterCentre = Involutes.CreatePt(innerRadius + xs, ys);

            // Find the start angle and the end angle for the curve. The curve starts
            // at the X axis and heads towards negative Y. The end angle is where the
            // curve becomes tangential to a radial from the centre of the ratchet.
            // If the cutter centre lies outside the pitch circle, then the ratchet
            // will not be able to have a tooth at right angles to the direction
            // of rotation, and the ratchet is able to skip teeth under high torque.
            // Nonetheless, we calculate the tooth shape and return a warning.

            double radiusOfCutterCentre = Involutes.DistanceBetween(PointF.Empty, cutterCentre);
            double cutterCentreAngle    = Math.Asin(-ys / radiusOfCutterCentre);
            double tangentAngle         = cutterCentreAngle
                                          + Math.Asin(cutterRadius / radiusOfCutterCentre);

            double endAngle   = Math.PI - Math.Atan2(-ys, xs);
            double startAngle = 3 * Math.PI / 2 - tangentAngle;

            points.Add(Involutes.RotateAboutOrigin
                           (-ToothAngle, PointAtAngle(ToothAngle - tangentAngle)));

            // Add the points for the cutter curve

            points.AddRange(Involutes.CirclePoints
                                (endAngle, startAngle, Involutes.AngleStep, cutterRadius, cutterCentre)
                            .Reverse());

            // Check that the radius of the cutter was not too great to
            // provide a latch at right angles to the radial from the centre
            // of the ratchet.

            double actualInnerRadius = Involutes.DistanceBetween(PointF.Empty, cutterCentre) - cutterRadius;
            double actualOuterRadius = Involutes.DistanceBetween(PointF.Empty, points[0]);

            if (Involutes.DistanceBetween(PointF.Empty, points[1]) > actualOuterRadius)
            {
                Information += "Cutter diameter too great for locking ratchet. Setting it to zero.\r\n";
                CutDiameter  = 0;
                CalculatePoints();
                return;
            }

            // Now add the slope

            for (double angle = 0; angle < ToothAngle - tangentAngle; angle += Involutes.AngleStep)
            {
                points.Add(PointAtAngle(angle));
            }
            OneToothProfile = Involutes.LinearReduction(points, (float)MaxError);
            Information    += $"Actual inner diameter: {2 * actualInnerRadius:N2}, "
                              + $"actual outer diameter: {2 * actualOuterRadius:N2}\r\n";
        }
Exemplo n.º 7
0
        /// <summary>
        /// Reflect a sequence of points to the opposite side of the X axis
        /// </summary>
        /// <param name="points">The points to be reflected</param>
        /// <returns>The reflected points</returns>

        public static IEnumerable <PointF> ReflectY(IEnumerable <PointF> points)
        => points.Select(p => Involutes.CreatePt(p.X, -p.Y));