private void InsertToothPath(Pinion pinion, PinionTooth tooth, PinionTooth nextTooth, StringBuilder pathBuilder)
        {
            pathBuilder.AppendFormat(CultureInfo.InvariantCulture, " L{0},{1}", (float)tooth.PitchCircleIntersectLeft.X, (float)tooth.PitchCircleIntersectLeft.Y);

            pathBuilder.AppendFormat(
                CultureInfo.InvariantCulture,
                " A{0},{1} 0 0,1 {2},{3}",
                (float)pinion.AddendumRadius, (float)pinion.AddendumRadius,
                (float)tooth.Apex.X, (float)tooth.Apex.Y);

            pathBuilder.AppendFormat(
                CultureInfo.InvariantCulture,
                " A{0},{1} 0 0,1 {2},{3}",
                (float)pinion.AddendumRadius, (float)pinion.AddendumRadius,
                (float)tooth.PitchCircleIntersectRight.X, (float)tooth.PitchCircleIntersectRight.Y);

            pathBuilder.AppendFormat(CultureInfo.InvariantCulture, " L{0},{1}", (float)tooth.DedendumIntersectRight.X, (float)tooth.DedendumIntersectRight.Y);

            double radius = pinion.PitchDiameter / 2.0 - pinion.Dedendum;

            pathBuilder.AppendFormat(
                CultureInfo.InvariantCulture,
                " A{0},{1} 0 0,1 {2},{3}",
                (float)radius, (float)radius,
                (float)nextTooth.DedendumIntersectLeft.X, (float)nextTooth.DedendumIntersectLeft.Y);
        }
        internal void Build(Pinion pinion, SvgSvgElement root)
        {
            SvgGroupElement helperLinesGroup = new SvgGroupElement("HelperLines");

            helperLinesGroup.Style = Styles.HelperLineStyle;
            root.AddChild(helperLinesGroup);

            // Wheel pitch circle
            helperLinesGroup.AddChild(SvgHelper.CreateCircle(pinion.Center, pinion.PitchDiameter / 2.0));

            // Wheel addendum circle
            helperLinesGroup.AddChild(SvgHelper.CreateCircle(pinion.Center, pinion.PitchDiameter / 2.0 + pinion.Addendum));

            // Wheel dedendum circle
            helperLinesGroup.AddChild(SvgHelper.CreateCircle(pinion.Center, pinion.PitchDiameter / 2.0 - pinion.Dedendum));

            // wheel center
            double halfCrossLength = 10;

            helperLinesGroup.AddChild(new SvgLineElement(pinion.Center.X - halfCrossLength, pinion.Center.Y, pinion.Center.X + halfCrossLength, pinion.Center.Y));
            helperLinesGroup.AddChild(new SvgLineElement(pinion.Center.X, pinion.Center.Y - halfCrossLength, pinion.Center.X, pinion.Center.Y + halfCrossLength));

            SvgGroupElement mainGroup = new SvgGroupElement("Main");

            mainGroup.Style = Styles.MinorLineStyle;
            root.AddChild(mainGroup);


            PinionTooth[] teeth       = pinion.GetTeeth(Math.PI / pinion.ToothCount);
            StringBuilder pathBuilder = new StringBuilder();

            pathBuilder.AppendFormat(CultureInfo.InvariantCulture, "M{0},{1}", (float)teeth[0].DedendumIntersectLeft.X, (float)teeth[0].DedendumIntersectLeft.Y);
            for (int i = 0; i < teeth.Length; i++)
            {
                PinionTooth tooth     = teeth[i];
                PinionTooth nextTooth = teeth[(i + 1) % teeth.Length];
                InsertToothPath(pinion, tooth, nextTooth, pathBuilder);
            }
            pathBuilder.Append(" z");


            SvgPath        svgPath        = new SvgPath(pathBuilder.ToString());
            SvgPathElement svgPathElement = new SvgPathElement();

            svgPathElement.D = svgPath;

            mainGroup.AddChild(svgPathElement);

            if (pinion.CenterHoleDiameter > 0)
            {
                mainGroup.AddChild(SvgHelper.CreateCircle(pinion.Center, pinion.CenterHoleDiameter / 2.0));
            }
        }
        internal void Build(Pinion pinion, SvgSvgElement root)
        {
            SvgGroupElement helperLinesGroup = new SvgGroupElement("HelperLines");
            helperLinesGroup.Style = Styles.HelperLineStyle;
            root.AddChild(helperLinesGroup);

            // Wheel pitch circle
            helperLinesGroup.AddChild(SvgHelper.CreateCircle(pinion.Center, pinion.PitchDiameter / 2.0));

            // Wheel addendum circle
            helperLinesGroup.AddChild(SvgHelper.CreateCircle(pinion.Center, pinion.PitchDiameter / 2.0 + pinion.Addendum));

            // Wheel dedendum circle
            helperLinesGroup.AddChild(SvgHelper.CreateCircle(pinion.Center, pinion.PitchDiameter / 2.0 - pinion.Dedendum));

            // wheel center
            double halfCrossLength = 10;
            helperLinesGroup.AddChild(new SvgLineElement(pinion.Center.X - halfCrossLength, pinion.Center.Y, pinion.Center.X + halfCrossLength, pinion.Center.Y));
            helperLinesGroup.AddChild(new SvgLineElement(pinion.Center.X, pinion.Center.Y - halfCrossLength, pinion.Center.X, pinion.Center.Y + halfCrossLength));

            SvgGroupElement mainGroup = new SvgGroupElement("Main");
            mainGroup.Style = Styles.MinorLineStyle;
            root.AddChild(mainGroup);

            PinionTooth[] teeth = pinion.GetTeeth(Math.PI / pinion.ToothCount);
            StringBuilder pathBuilder = new StringBuilder();

            pathBuilder.AppendFormat(CultureInfo.InvariantCulture, "M{0},{1}", (float)teeth[0].DedendumIntersectLeft.X, (float)teeth[0].DedendumIntersectLeft.Y);
            for (int i = 0; i < teeth.Length; i++)
            {
                PinionTooth tooth = teeth[i];
                PinionTooth nextTooth = teeth[(i + 1) % teeth.Length];
                InsertToothPath(pinion, tooth, nextTooth, pathBuilder);
            }
            pathBuilder.Append(" z");

            SvgPath svgPath = new SvgPath(pathBuilder.ToString());
            SvgPathElement svgPathElement = new SvgPathElement();
            svgPathElement.D = svgPath;

            mainGroup.AddChild(svgPathElement);

            if (pinion.CenterHoleDiameter > 0)
            {
                mainGroup.AddChild(SvgHelper.CreateCircle(pinion.Center, pinion.CenterHoleDiameter / 2.0));
            }
        }
        public string Build()
        {
            double border = 5;             // border around grahics in mm

            Wheel  wheel  = m_CycloidalGear.Wheel;
            Pinion pinion = m_CycloidalGear.Pinion;

            double pageWidth  = wheel.Addendum + wheel.PitchDiameter + pinion.PitchDiameter + pinion.Addendum + 2 * border;
            double pageHeight = 2 * wheel.Addendum + wheel.PitchDiameter + 2 * border;
            Page   page       = new Page((float)pageWidth, (float)pageHeight, SvgLengthType.SVG_LENGTHTYPE_MM);

            SvgSvgElement root = new SvgSvgElement(
                page.SvgLengthWidth, page.SvgLengthHeight,
                new SvgNumList(new float[] { -(float)(wheel.Addendum + wheel.PitchDiameter / 2.0 + border), -page.Height / 2, page.Width, page.Height }));

            wheel.Center  = new Point(0, 0);
            pinion.Center = wheel.Center + new Vector(m_CycloidalGear.WheelPinionDistance, 0);

            new WheelGenerator().Build(m_CycloidalGear.Wheel, root);
            new PinionGenerator().Build(m_CycloidalGear.Pinion, root);

            return(root.WriteSVGString(true));
        }
        private void InsertToothPath(Pinion pinion, PinionTooth tooth, PinionTooth nextTooth, StringBuilder pathBuilder)
        {
            pathBuilder.AppendFormat(CultureInfo.InvariantCulture, " L{0},{1}", (float)tooth.PitchCircleIntersectLeft.X, (float)tooth.PitchCircleIntersectLeft.Y);

            pathBuilder.AppendFormat(
                CultureInfo.InvariantCulture,
                " A{0},{1} 0 0,1 {2},{3}",
                (float)pinion.AddendumRadius, (float)pinion.AddendumRadius,
                (float)tooth.Apex.X, (float)tooth.Apex.Y);

            pathBuilder.AppendFormat(
                CultureInfo.InvariantCulture,
                " A{0},{1} 0 0,1 {2},{3}",
                (float)pinion.AddendumRadius, (float)pinion.AddendumRadius,
                (float)tooth.PitchCircleIntersectRight.X, (float)tooth.PitchCircleIntersectRight.Y);

            pathBuilder.AppendFormat(CultureInfo.InvariantCulture, " L{0},{1}", (float)tooth.DedendumIntersectRight.X, (float)tooth.DedendumIntersectRight.Y);

            double radius = pinion.PitchDiameter / 2.0 - pinion.Dedendum;
            pathBuilder.AppendFormat(
                CultureInfo.InvariantCulture,
                " A{0},{1} 0 0,1 {2},{3}",
                (float)radius, (float)radius,
                (float)nextTooth.DedendumIntersectLeft.X, (float)nextTooth.DedendumIntersectLeft.Y);
        }