Beispiel #1
0
        double[] ComputeAngles(Circle[] circles)
        {
            int count = circles.Length;

            var angles = new double[count];

            for (int i = 0; i < count; i++)
            {
                int otherIndex = i == count - 1 ? 0 : i + 1;
                angles[i] = AddInHelper.AngleBetween(circles[i].Axis.Direction, circles[otherIndex].Axis.Direction) / 2;
            }

            angles[count - 1] = Math.PI / 2 - angles[count - 1];
            return(angles);
        }
Beispiel #2
0
        public void Render()
        {
            renderedBody = CreateUnfoldedFaceBody();
            DesignBody designBody = DesignBody.Create(flatBody.FlatPart, Resources.FlatFaceName, renderedBody);

            designBody.Layer = NoteHelper.CreateOrGetLayer(Window.ActiveWindow.Document, Resources.FlatFaceLayerName, System.Drawing.Color.Beige);

            foreach (FlatLoop flatLoop in Loops)
            {
                foreach (FlatFin flatFin in flatLoop.Fins.Where(f => !f.IsInternal))
                {
                    DesignCurve designCurve = DesignCurve.Create(flatBody.FlatPart, flatFin.SourceFin.Edge);
                    designCurve.Transform(transform);
                    designCurve.Layer = NoteHelper.CreateOrGetLayer(Window.ActiveWindow.Document, Resources.FlatCuttingLinesLayerName, System.Drawing.Color.Blue);
                }

                foreach (FlatFin flatFin in flatLoop.Fins.Where(f => f.AdjacentFin != null))
                {
                    if (
                        flatBody.FlatPattern.IsCreatingDashes &&
                        Accuracy.CompareAngles(AddInHelper.AngleBetween(flatFin.FlatFace.SourceFace.Geometry.Evaluate(PointUV.Origin).Normal, flatFin.AdjacentFin.FlatFace.SourceFace.Geometry.Evaluate(PointUV.Origin).Normal), flatBody.FlatPattern.BreakAngle) <= 0)
                    {
                        Layer breakLayer = NoteHelper.CreateOrGetLayer(Window.ActiveWindow.Document, Resources.BreakLinesLayerName, System.Drawing.Color.DarkBlue);
                        if (flatBody.FlatPattern.DashSize == 0)
                        {
                            DesignCurve desCurve = DesignCurve.Create(FlatBody.FlatPart, flatFin.AsCurveSegment());
                            desCurve.Layer = breakLayer;
                        }
                        else
                        {
                            DashesButtonCapsule.CreateDashes(flatFin.AsCurveSegment(), FlatBody.FlatPart, flatBody.FlatPattern.DashSize, breakLayer);
                        }
                    }
                }
            }
        }
Beispiel #3
0
        public void Iterate()
        {
            Iteration++;

            var newVParameters    = new CircularList <CircularList <double> >(iSteps * 2);
            var backupVParameters = new CircularList <CircularList <double> >(iSteps * 2);
            var newTabAngles      = new CircularList <CircularList <double> >(iSteps * 2);

            for (int i = 0; i < iSteps * 2; i++)
            {
                newVParameters.Add(new CircularList <double>(jSteps));
                backupVParameters.Add(new CircularList <double>(jSteps));
                newTabAngles.Add(new CircularList <double>(jSteps));
                for (int j = 0; j < jSteps; j++)
                {
                    newVParameters[i].Add(vParameters[i][j]);
                    backupVParameters[i].Add(vParameters[i][j]);
                    newTabAngles[i].Add(tabAngles[i][j]);
                }
            }

            double cumulativeErrorTally = 0;

            MaxError = 0;
            for (int i = 0; i < iSteps * 2; i++)
            {
                for (int j = 0; j < jSteps; j++)
                {
                    bool swap      = j % 2 == 0;
                    int  iOtherDir = swap ? -1 : 1;
                    int  iOther    = i + iOtherDir;

                    Circle baseCircle = GetTabFromPoints(true, i, j, iOther);
                    Circle circle0    = GetTabFromPoints(true, iOther, j - 1, i);
                    Circle circle1    = GetTabFromPoints(true, iOther, j + 1, i);

                    double distance0 = (baseCircle.Frame.Origin - circle0.Frame.Origin).Magnitude - baseCircle.Radius - circle0.Radius;
                    double distance1 = (baseCircle.Frame.Origin - circle1.Frame.Origin).Magnitude - baseCircle.Radius - circle1.Radius;
                    cumulativeErrorTally += distance0 * distance0 + distance1 * distance1;
                    MaxError              = Math.Max(Math.Abs(distance0), MaxError);
                    MaxError              = Math.Max(Math.Abs(distance1), MaxError);

                    double angleAdjust = (distance0 + distance1) / 2 * AngleForce / GetSpanAt(i, j) / baseCircle.Radius;                    // / GetSpanAt(i, j) / baseCircle.Radius; // / baseCircle.Radius;
                    newTabAngles[i][j] -= angleAdjust;

                    newTabAngles[i][j - 1] -= angleAdjust / 2;
                    newTabAngles[i][j + 1] -= angleAdjust / 2;

                    double iAngle = AddInHelper.AngleBetween(
                        circle0.Frame.Origin - baseCircle.Frame.Origin,
                        circle1.Frame.Origin - baseCircle.Frame.Origin
                        );

                    double vOffset = (distance1 - distance0) * VForce;
                    //double uAngleOffset = -(Math.PI / 2 - Math.Abs(iAngle)) * UAngleForce;
                    double uAngleOffset = -(Math.PI * 2 / 3 - Math.Abs(iAngle)) * UAngleForce;

                    Circle circleV      = GetTabFromPoints(true, iOther, j, i);
                    double distanceV    = (baseCircle.Frame.Origin - circleV.Frame.Origin).Magnitude - baseCircle.Radius - circleV.Radius;
                    double uTouchOffset = -distanceV * UTouchForce;

                    double averageOffset = 0;
                    double averageAngle  = 0;
                    double count         = 0;

#if false
                    for (int ii = i - 1; ii <= i + 1; ii++)
                    {
                        for (int jj = j - 2; jj <= j + 2; jj++)
                        {
                            if (i == ii && j == jj)
                            {
                                continue;
                            }

                            double weight = (double)1 / (Math.Pow(i - ii, 2) + Math.Pow(j - jj, 2));
                            averageOffset += GetSpanAt(ii, jj) * weight;
                            averageAngle  += GetTabFromPoints(true, i, j, j % 2 == 0 ? i - 1 : i + 1).Radius *weight;
                            count         += weight;
                        }
                    }

                    averageOffset  = averageOffset / count - GetSpanAt(i, j);
                    averageOffset *= -AverageVForce / 2;

                    averageAngle        = averageAngle / count - baseCircle.Radius;
                    newTabAngles[i][j] += averageAngle * AverageTabAngleForce;
#elif true
                    foreach (int ii in new int[] { i, iOther })
                    {
                        foreach (int jj in new int[] { j - 1, j + 1 })
                        {
                            averageAngle += GetTabFromPoints(true, ii, jj, ii == i ? iOther : i).Radius;
                            count++;
                        }
                    }

                    averageOffset += GetSpanAt(i - 1, j);
                    averageOffset += GetSpanAt(i + 1, j);
                    averageOffset += GetSpanAt(i, j - 1);
                    averageOffset += GetSpanAt(i, j + 1);
                    averageOffset /= 4;

                    averageOffset  = averageOffset / count - GetSpanAt(i, j);
                    averageOffset *= -AverageVForce / 2;

                    averageAngle        = averageAngle / count - baseCircle.Radius;
                    newTabAngles[i][j] -= averageAngle * AverageTabAngleForce;
#else
                    Point midpointV = GetFivePointNurbsAverage(new int[, ] {
                        { i, j - 2 },
                        { i, j - 1 },
                        { i, j },
                        { i, j + 1 },
                        { i, j + 2 }
                    });

                    Point midpointD0 = GetFivePointNurbsAverage(new int[, ] {
                        { i - iOtherDir, j - 2 },
                        { i, j - 1 },
                        { i, j },
                        { i + iOtherDir, j + 1 },
                        { i + 2 * iOtherDir, j + 2 }
                    });

                    Point midpointD1 = GetFivePointNurbsAverage(new int[, ] {
                        { i - iOtherDir, j + 2 },
                        { i, j + 1 },
                        { i, j },
                        { i + iOtherDir, j - 1 },
                        { i + 2 * iOtherDir, j - 2 }
                    });

                    Point midpointU = GetFivePointNurbsAverage(new int[, ] {
                        { i - 2 * iOtherDir, j },
                        { i - iOtherDir, j },
                        { i, j },
                        { i + iOtherDir, j },
                        { i + 2 * iOtherDir, j }
                    });

                    averageOffset  = (midpointV.Y + midpointU.Y) / 2 - GetSpanAt(i, j);
                    averageOffset *= -AverageVForce / 2;

                    averageAngle        = (midpointV.X + 2 * midpointD0.X + 2 * midpointD1.X) / 5 - tabAngles[i][j];
                    newTabAngles[i][j] += averageAngle * AverageTabAngleForce;
#endif

                    double size = 1;                    // (points[i][j + 1] - points[i][j]).Magnitude;
                    double slip = (uAngleOffset + averageOffset + uTouchOffset) * size;

                    newVParameters[i][j]     += vOffset + slip;
                    newVParameters[i][j + 1] += vOffset - slip;

                    newVParameters[i][j - 1] += (vOffset + slip) / 2;
                    newVParameters[i][j + 2] += (vOffset - slip) / 2;

                    //				double oldSpan = (points[i][j + 1] - points[i][j]).Magnitude;
                    //				double newSpan = (points[i][j + 1] - points[i][j]).Magnitude;


                    Trace.WriteIf(Iteration % 400 == 0, tabAngles[i][j] + " ");
                    //					Trace.WriteIf(Iteration % 400 == 0, iAngle + " ");
                    //					Trace.WriteIf(Iteration % 400 == 0, GetSpanAt(i,j) + " ");
                }
                Trace.WriteLineIf(Iteration % 400 == 0, "");
            }

            for (int i = 0; i < iSteps * 2; i++)
            {
                for (int j = 0; j < jSteps; j++)
                {
                    newTabAngles[i][j] = Math.Max(Math.PI / 2, newTabAngles[i][j]);
                    newTabAngles[i][j] = Math.Min(Math.PI * 3 / 4, newTabAngles[i][j]);

                    double l1 = backupVParameters[i][j + 1] - backupVParameters[i][j];
                    double l2 = newVParameters[i][j + 1] - newVParameters[i][j];
                    double b1 = Math.PI - tabAngles[i][j];

                    double a   = l1 / l2 / Math.Tan(b1 / 2) * (1 + 1 / Math.Cos(b1 / 2));
                    double phi = 2 * Math.Atan(1 / a);
                    tabAngles[i][j] = Math.PI - 2 * phi;

                    //double b2 = 2 * Math.Asin(l2 / l1 * Math.Sin(b1 / 2));
                    //tabAngles[i][j] = Math.PI - b2;
                }
            }

            for (int i = 0; i < iSteps * 2; i++)
            {
                // make intersecting tabs identical

                //double angle = (
                //    newTabAngles[i][0] +
                //    newTabAngles[i + iSteps][0] +
                //    newTabAngles[i + iSteps / 2][jSteps / 2] +
                //    newTabAngles[i + 3 * iSteps / 2][jSteps / 2]
                //) / 4;

                //newTabAngles[i][0] = angle;
                //newTabAngles[i + iSteps][0] = angle;
                //newTabAngles[i + iSteps / 2][jSteps / 2] = angle;
                //newTabAngles[i + 3 * iSteps / 2][jSteps / 2] = angle;

                double span = (
                    (newVParameters[i][1] - newVParameters[i][0]) +
                    (newVParameters[i + iSteps][1] - newVParameters[i + iSteps][0]) +
                    (newVParameters[i + iSteps / 2][jSteps / 2 + 1] - newVParameters[i + iSteps / 2][jSteps / 2]) +
                    (newVParameters[i + 3 * iSteps / 2][jSteps / 2 + 1] - newVParameters[i + 3 * iSteps / 2][jSteps / 2])
                    ) / 8;

                newVParameters[i][0]          = -span;
                newVParameters[i][1]          = span;
                newVParameters[i + iSteps][0] = -span;
                newVParameters[i + iSteps][1] = span;
                newVParameters[i + iSteps / 2][jSteps / 2]         = Math.PI - span;
                newVParameters[i + iSteps / 2][jSteps / 2 + 1]     = Math.PI + span;
                newVParameters[i + 3 * iSteps / 2][jSteps / 2]     = Math.PI - span;
                newVParameters[i + 3 * iSteps / 2][jSteps / 2 + 1] = Math.PI + span;
            }

            // Average antipodal points
            // for l(i, j),
            // l(i, j) == l(-i, pi+j)* == l(i+2pi, -j) == l(-i-2pi, pi-j)*
            // Where * means x=x, y=-y, z=-z
            for (int i = 0; i < iSteps * 2; i++)
            {
                for (int j = 0; j < jSteps / 2; j++)
                {
                    double average = (
                        newVParameters[i][j] +
                        newVParameters[-i][j + jSteps / 2] - Math.PI +
                        (j < 2 ? 0 : 2 * Math.PI) - newVParameters[i + iSteps][-j + 1] +
                        Math.PI - newVParameters[-i - iSteps][-j + jSteps / 2 + 1]
                        ) / 4;

                    newVParameters[i][j] = average;
                    newVParameters[-i][j + jSteps / 2] = average + Math.PI;
                    newVParameters[i + iSteps][-j + 1] = (j < 2 ? 0 : 2 * Math.PI) - average;
                    newVParameters[-i - iSteps][-j + jSteps / 2 + 1] = Math.PI - average;

                    average = (
                        tabAngles[i][j] +
                        tabAngles[-i][j + jSteps / 2 + 1] +
                        tabAngles[i + iSteps][-j] +
                        tabAngles[-i - iSteps][-j + jSteps / 2 + 1]
                        ) / 4;

                    tabAngles[i][j] = average;
                    tabAngles[-i][j + jSteps / 2 + 1]           = average;
                    tabAngles[i + iSteps][-j]                   = average;
                    tabAngles[-i - iSteps][-j + jSteps / 2 + 1] = average;
                }
            }

            CumulativeError = Math.Sqrt(cumulativeErrorTally / (iSteps * 2 * jSteps * 2));
            //	Trace.WriteLine(lastCumulativeError);

            // We're not calculating the points for the last iteration.  Whatevs.
            vParameters = newVParameters;
            tabAngles   = newTabAngles;

            for (int i = 0; i < iSteps * 2; i++)
            {
                double u = 2 * Math.PI * (double)i / iSteps;
                for (int j = 0; j < jSteps; j++)
                {
                    points[i][j] = Lawson.Evaluate(PointUV.Create(vParameters[i][j], u), p, q, circleAngle, inverseOffset, true) * scale;
                    //		Trace.WriteLine(string.Format("{0} {1} {2}", i, j, tabAngles[i][j]));
                }
            }
        }
Beispiel #4
0
        public void Iterate()
        {
            Iteration++;

            //var newVParameters = new List<List<double>>(steps + 1);
            //var backupVParameters = new List<List<double>>(steps + 1);
            //var newTabAngles = new List<List<double>>(steps + 1);

            for (int i = 0; i < steps; i++)
            {
                //newVParameters.Add(new List<double>(steps + 1));
                //backupVParameters.Add(new List<double>(steps + 1));
                //newTabAngles.Add(new List<double>(steps + 1));
                for (int j = 0; j <= steps; j++)
                {
                    //		newVParameters[i].Add(vParameters[i][j]);
                    //		backupVParameters[i].Add(vParameters[i][j]);
                    //newTabAngles[i].Add(tabAngles[i][j]);
                }
            }

            double cumulativeErrorTally = 0;

            MaxError = 0;
            for (int i = 0; i <= steps; i++)
            {
                for (int j = 0; j <= steps; j++)
                {
                    Vector grad = Gradient(points[i, j]);
                    points[i, j] = points[i, j] + grad.Z * Direction.DirZ / 100;

#if false
                    bool swap      = j % 2 == 0;
                    int  iOtherDir = swap ? -1 : 1;
                    int  iOther    = i + iOtherDir;

                    Circle baseCircle = GetTabFromPoints(true, i, j, iOther);
                    Circle circle0    = GetTabFromPoints(true, iOther, j - 1, i);
                    Circle circle1    = GetTabFromPoints(true, iOther, j + 1, i);

                    double distance0 = (baseCircle.Frame.Origin - circle0.Frame.Origin).Magnitude - baseCircle.Radius - circle0.Radius;
                    double distance1 = (baseCircle.Frame.Origin - circle1.Frame.Origin).Magnitude - baseCircle.Radius - circle1.Radius;
                    cumulativeErrorTally += distance0 * distance0 + distance1 * distance1;
                    MaxError              = Math.Max(Math.Abs(distance0), MaxError);
                    MaxError              = Math.Max(Math.Abs(distance1), MaxError);

                    double angleAdjust = (distance0 + distance1) / 2 * AngleForce / GetSpanAt(i, j) / baseCircle.Radius;                     // / GetSpanAt(i, j) / baseCircle.Radius; // / baseCircle.Radius;
                    newTabAngles[i][j] -= angleAdjust;

                    newTabAngles[i][j - 1] -= angleAdjust / 2;
                    newTabAngles[i][j + 1] -= angleAdjust / 2;

                    double iAngle = AddInHelper.AngleBetween(
                        circle0.Frame.Origin - baseCircle.Frame.Origin,
                        circle1.Frame.Origin - baseCircle.Frame.Origin
                        );

                    double vOffset = (distance1 - distance0) * VForce;
                    //double uAngleOffset = -(Math.PI / 2 - Math.Abs(iAngle)) * UAngleForce;
                    double uAngleOffset = -(Math.PI * 2 / 3 - Math.Abs(iAngle)) * UAngleForce;

                    Circle circleV      = GetTabFromPoints(true, iOther, j, i);
                    double distanceV    = (baseCircle.Frame.Origin - circleV.Frame.Origin).Magnitude - baseCircle.Radius - circleV.Radius;
                    double uTouchOffset = -distanceV * UTouchForce;

                    double averageOffset = 0;
                    double averageAngle  = 0;
                    double count         = 0;


                    foreach (int ii in new int[] { i, iOther })
                    {
                        foreach (int jj in new int[] { j - 1, j + 1 })
                        {
                            averageAngle += GetTabFromPoints(true, ii, jj, ii == i ? iOther : i).Radius;
                            count++;
                        }
                    }

                    averageOffset += GetSpanAt(i - 1, j);
                    averageOffset += GetSpanAt(i + 1, j);
                    averageOffset += GetSpanAt(i, j - 1);
                    averageOffset += GetSpanAt(i, j + 1);
                    averageOffset /= 4;

                    averageOffset  = averageOffset / count - GetSpanAt(i, j);
                    averageOffset *= -AverageVForce / 2;

                    averageAngle        = averageAngle / count - baseCircle.Radius;
                    newTabAngles[i][j] -= averageAngle * AverageTabAngleForce;

                    double size = 1;                    // (points[i][j + 1] - points[i][j]).Magnitude;
                    double slip = (uAngleOffset + averageOffset + uTouchOffset) * size;

                    newVParameters[i][j]     += vOffset + slip;
                    newVParameters[i][j + 1] += vOffset - slip;

                    newVParameters[i][j - 1] += (vOffset + slip) / 2;
                    newVParameters[i][j + 2] += (vOffset - slip) / 2;

                    //				double oldSpan = (points[i][j + 1] - points[i][j]).Magnitude;
                    //				double newSpan = (points[i][j + 1] - points[i][j]).Magnitude;


                    Trace.WriteIf(Iteration % 400 == 0, tabAngles[i][j] + " ");
                    //					Trace.WriteIf(Iteration % 400 == 0, iAngle + " ");
                    //					Trace.WriteIf(Iteration % 400 == 0, GetSpanAt(i,j) + " ");
#endif
                }
                Trace.WriteLineIf(Iteration % 400 == 0, "");
            }

#if false
            // Average antipodal points
            // for l(i, j),
            // l(i, j) == l(-i, pi+j)* == l(i+2pi, -j) == l(-i-2pi, pi-j)*
            // Where * means x=x, y=-y, z=-z
            for (int i = 0; i < iSteps; i++)
            {
                for (int j = 0; j < jSteps / 2; j++)
                {
                    double average = (
                        newVParameters[i][j] +
                        newVParameters[-i][j + jSteps / 2] - Math.PI +
                        (j < 2 ? 0 : 2 * Math.PI) - newVParameters[i + iSteps][-j + 1] +
                        Math.PI - newVParameters[-i - iSteps][-j + jSteps / 2 + 1]
                        ) / 4;

                    newVParameters[i][j] = average;
                    newVParameters[-i][j + jSteps / 2] = average + Math.PI;
                    newVParameters[i + iSteps][-j + 1] = (j < 2 ? 0 : 2 * Math.PI) - average;
                    newVParameters[-i - iSteps][-j + jSteps / 2 + 1] = Math.PI - average;

                    average = (
                        tabAngles[i][j] +
                        tabAngles[-i][j + jSteps / 2 + 1] +
                        tabAngles[i + iSteps][-j] +
                        tabAngles[-i - iSteps][-j + jSteps / 2 + 1]
                        ) / 4;

                    tabAngles[i][j] = average;
                    tabAngles[-i][j + jSteps / 2 + 1]           = average;
                    tabAngles[i + iSteps][-j]                   = average;
                    tabAngles[-i - iSteps][-j + jSteps / 2 + 1] = average;
                }
            }
#endif

            CumulativeError = Math.Sqrt(cumulativeErrorTally / (steps * steps * 2));
            //	Trace.WriteLine(lastCumulativeError);

            // We're not calculating the points for the last iteration.  Whatevs.
            //		vParameters = newVParameters;

            //tabAngles = newTabAngles;

#if false
            for (int i = 0; i < iSteps; i++)
            {
                double u = 2 * Math.PI * (double)i / iSteps;
                for (int j = 0; j < jSteps; j++)
                {
                    points[i][j] = Gyroid.Evaluate(PointUV.Create(vParameters[i][j], u), p, q, circleAngle, inverseOffset, true) * scale;
                    //		Trace.WriteLine(string.Format("{0} {1} {2}", i, j, tabAngles[i][j]));
                }
            }
#endif
        }
Beispiel #5
0
        private static double AngleBetween(List <Component> chain, int i)
        {
            int numGears = chain.Count;

            return(AddInHelper.AngleBetween(chain[i].Placement.Translation - chain[(i + 1) % numGears].Placement.Translation, chain[i].Placement.Translation - chain[(i + numGears - 1) % numGears].Placement.Translation));
        }
Beispiel #6
0
        protected override void OnExecute(Command command, ExecutionContext context, System.Drawing.Rectangle buttonRect)
        {
            double lengthConversion = ActiveWindow.Units.Length.ConversionFactor;

            int  numberOfTeethL = (int)Values[Resources.NumberOfTeethLText].Value;
            int  numberOfTeethR = (int)Values[Resources.NumberOfTeethRText].Value;
            bool isInternalL    = numberOfTeethL < 0;
            bool isInternalR    = numberOfTeethR < 0;

            numberOfTeethL = Math.Abs(numberOfTeethL);
            numberOfTeethR = Math.Abs(numberOfTeethR);

            double pressureAngle     = Values[Resources.PressureAngleText].Value * Math.PI / 180;
            double module            = Values[Resources.ModuleText].Value / lengthConversion;
            double dedendumClearance = Values[Resources.DedendumClearanceText].Value;
            double depth             = Values[Resources.DepthText].Value / lengthConversion;

            bool useTrochoidalInterferenceRemoval = Booleans[Resources.UseTrochoidalText].Value;
            bool addDedendumClearance             = Booleans[Resources.AddDedendumClearance].Value;

            if (!addDedendumClearance)
            {
                dedendumClearance = 0;
            }

            bool   isBevel        = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsBevelText].IsEnabledCommandBoolean.Value;
            double bevelAngle     = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsBevelText].Values[Resources.BevelAngleText].Value * Math.PI / 180;
            double bevelKneeRatio = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsBevelText].Values[Resources.BevelKneeRatioText].Value;

            bool   isHelical    = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHelicalText].IsEnabledCommandBoolean.Value;
            double helicalAngle = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHelicalText].Values[Resources.HelicalAngleText].Value * Math.PI / 180;

            if (!isHelical)
            {
                helicalAngle = 0;
            }

            bool   isScrew          = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsScrewText].IsEnabledCommandBoolean.Value;
            double screwAngle       = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsScrewText].Values[Resources.ScrewAngleText].Value * Math.PI / 180;
            double screwAngleOffset = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsScrewText].Values[Resources.ScrewAngleBiasText].Value * Math.PI / 180;

            if (!isScrew)
            {
                screwAngle       = 0;
                screwAngleOffset = 0;
            }

            double screwAngleAverage = screwAngle / 2;
            double screwAngleL       = screwAngleAverage + screwAngleOffset;
            double screwAngleR       = screwAngleAverage - screwAngleOffset;

            bool   isHypoid     = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHypoidText].IsEnabledCommandBoolean.Value;
            double hypoidAngle  = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHypoidText].Values[Resources.HypoidAngleText].Value * Math.PI / 180;
            double hypoidOffset = RibbonBooleanGroupCapsule.BooleanGroupCapsules[Resources.IsHypoidText].Values[Resources.HypoidOffsetText].Value / lengthConversion;

            if (!isHypoid)
            {
                hypoidAngle  = 0;
                hypoidOffset = 0;
            }

            Frame frame = Frame.World;
            //Circle circle = SelectedCircle(ActiveWindow);
            //if (circle != null)
            //    frame = circle.Frame;

            List <ITrimmedCurve> selectedCurves = ActiveWindow.GetAllSelectedITrimmedCurves().ToList();

            if (selectedCurves.Count == 2 && selectedCurves[0].Geometry is Circle && selectedCurves[0].Geometry is Circle)
            {
                Circle     circle0    = (Circle)selectedCurves[0].Geometry;
                Circle     circle1    = (Circle)selectedCurves[1].Geometry;
                Separation separation = circle0.Axis.GetClosestSeparation(circle1.Axis);

                if (Accuracy.LengthIsZero(separation.Distance))
                {
                    throw new NotImplementedException("Distance between axes is zero; only hypoid implemented.");
                }

                isHypoid     = true;
                hypoidAngle  = AddInHelper.AngleBetween(circle0.Axis.Direction, circle1.Axis.Direction);
                hypoidOffset = ((circle0.Frame.Origin - separation.PointA).Magnitude - depth / 2) / Math.Cos(hypoidAngle / 2);

                double radiusAApprox = separation.Distance * circle0.Radius / (circle0.Radius + circle1.Radius);
                double radiusBApprox = separation.Distance - radiusAApprox;
                numberOfTeethR = (int)Math.Round((double)numberOfTeethL / radiusAApprox * radiusBApprox);
                module         = radiusAApprox * 2 / numberOfTeethL;

                Point     midpoint = separation.PointA + (separation.PointA - separation.PointB) * numberOfTeethL / numberOfTeethR;
                Direction sideSide = (circle0.Frame.Origin - circle1.Frame.Origin).Direction;
                frame = Frame.Create(midpoint, Direction.Cross(sideSide, -(midpoint - circle0.GetClosestSeparation(circle1).PointA).Direction), sideSide);
            }

            double hypoidAngleL = Math.Atan(Math.Sin(hypoidAngle) / (Math.Cos(hypoidAngle) + (double)numberOfTeethR / numberOfTeethL));
            double hypoidAngleR = Math.Atan(Math.Sin(hypoidAngle) / (Math.Cos(hypoidAngle) + (double)numberOfTeethL / numberOfTeethR));

            Gear gearL = null;
            Gear gearR = null;

            var          gearDataL     = new GearData(numberOfTeethL, pressureAngle, module, dedendumClearance, isInternalL, screwAngleL);
            var          gearDataR     = new GearData(numberOfTeethR, pressureAngle, module, dedendumClearance, isInternalR, screwAngleR);
            ToothProfile toothProfileL = GetGearProfileFromOptions(gearDataL, gearDataR, useTrochoidalInterferenceRemoval, addDedendumClearance);
            ToothProfile toothProfileR = GetGearProfileFromOptions(gearDataR, gearDataL, useTrochoidalInterferenceRemoval, addDedendumClearance);

            if (isBevel)
            {
                gearL = BevelGear.Create(ActiveIPart, gearDataL, gearDataR, toothProfileL, helicalAngle, bevelAngle, bevelKneeRatio, depth);
                gearR = BevelGear.Create(ActiveIPart, gearDataR, gearDataL, toothProfileR, -helicalAngle, bevelAngle, bevelKneeRatio, depth);
            }
            else if (isHypoid)
            {
                gearL = HypoidGear.Create(ActiveIPart, gearDataL, gearDataR, toothProfileL, helicalAngle, hypoidAngleL, hypoidOffset, bevelKneeRatio, depth);
                gearR = HypoidGear.Create(ActiveIPart, gearDataR, gearDataL, toothProfileR, -helicalAngle, hypoidAngleR, hypoidOffset, bevelKneeRatio, depth);
            }
            else
            {
                gearL = StraightGear.Create(ActiveIPart, gearDataL, gearDataR, toothProfileL, helicalAngle, screwAngleL, depth);
                gearR = StraightGear.Create(ActiveIPart, gearDataR, gearDataL, toothProfileR, -helicalAngle, screwAngleR, depth);
            }

            Line zAxis = Line.Create(Point.Origin, Direction.DirZ);

            gearL.Component.Transform(
                Matrix.CreateMapping(frame) *
                Matrix.CreateRotation(zAxis, Math.PI) *
                gearL.TransformToTangent *
                Matrix.CreateRotation(zAxis, gearDataL.PitchAngle * ((double)1 / 2 + (gearDataL.NumberOfTeeth % 2 == 0 && !isHypoid ? -1 : 0)))
                );

            gearR.Component.Transform(
                Matrix.CreateMapping(frame) *
                gearR.TransformToTangent *
                Matrix.CreateRotation(zAxis, gearDataR.PitchAngle * ((double)1 / 2 + (gearDataR.NumberOfTeeth % 2 == 0 && !isHypoid ? -1 : 0)))
                );


            //		if (gearDataR.NumberOfTeeth % 2 == 0)
            //			gearR.Component.Transform(Matrix.CreateRotation(Line.Create(Point.Origin, Direction.DirZ), gearDataR.PitchAngle));

            //gearR.Component.Transform(gearR.TransformToTangent);

            Part        parent       = ActiveIPart.Master;
            IDesignFace pitchCircleL = gearL.Component.Content.Bodies.Where(b => b.Master == gearL.PitchCircleDesBody).First().Faces.First();
            IDesignFace pitchCircleR = gearR.Component.Content.Bodies.Where(b => b.Master == gearR.PitchCircleDesBody).First().Faces.First();

            Part        gearMountPart      = Part.Create(parent.Document, String.Format(Resources.GearMountPartName, gearDataL.NumberOfTeeth, gearDataR.NumberOfTeeth));
            Component   gearMountComponent = Component.Create(parent, gearMountPart);
            DesignBody  mountBodyL         = DesignBody.Create(gearMountPart, string.Format(Resources.MountBodyName, gearDataL.NumberOfTeeth), pitchCircleL.Master.Shape.Body.CreateTransformedCopy(pitchCircleL.TransformToMaster.Inverse));
            DesignBody  mountBodyR         = DesignBody.Create(gearMountPart, string.Format(Resources.MountBodyName, gearDataR.NumberOfTeeth), pitchCircleR.Master.Shape.Body.CreateTransformedCopy(pitchCircleR.TransformToMaster.Inverse));
            IDesignFace mountCircleL       = gearMountComponent.Content.Bodies.Where(b => b.Master == mountBodyL).First().Faces.First();
            IDesignFace mountCircleR       = gearMountComponent.Content.Bodies.Where(b => b.Master == mountBodyR).First().Faces.First();

            Layer mountLayer = NoteHelper.CreateOrGetLayer(ActiveDocument, Resources.GearMountAlignmentCircleLayer, System.Drawing.Color.LightGray);

            mountLayer.SetVisible(null, false);
            mountBodyL.Layer = mountLayer;
            mountBodyR.Layer = mountLayer;

            MatingCondition matingCondition;

            matingCondition = AnchorCondition.Create(parent, gearMountComponent);
            matingCondition = AlignCondition.Create(parent, mountCircleL, pitchCircleL);
            matingCondition = AlignCondition.Create(parent, mountCircleR, pitchCircleR);
            //		matingCondition = TangentCondition.Create(parent, pitchCircleL, pitchCircleR);
            GearCondition gearCondition = GearCondition.Create(parent, pitchCircleL, pitchCircleR);

            if (gearDataL.IsInternal ^ gearDataR.IsInternal)
            {
                gearCondition.IsBelt = true;
            }

            ActiveWindow.InteractionMode = InteractionMode.Solid;

            Settings.Default.NumberOfTeethL       = numberOfTeethL;
            Settings.Default.NumberOfTeethR       = numberOfTeethR;
            Settings.Default.PressureAngleDegrees = pressureAngle * 180 / Math.PI;
            Settings.Default.Module            = module;
            Settings.Default.Depth             = depth;
            Settings.Default.DedendumClearance = dedendumClearance;

            Settings.Default.UseTrochoidalInterferenceRemoval = useTrochoidalInterferenceRemoval;
            Settings.Default.AddDedendumClearace = addDedendumClearance;

            Settings.Default.IsBevel = isBevel;
            if (isBevel)
            {
                Settings.Default.BevelAngle     = bevelAngle * 180 / Math.PI;
                Settings.Default.BevelKneeRatio = bevelKneeRatio;
            }

            Settings.Default.IsHelical    = isHelical;
            Settings.Default.HelicalAngle = helicalAngle * 180 / Math.PI;

            Settings.Default.IsScrew          = isScrew;
            Settings.Default.ScrewAngle       = screwAngle * 180 / Math.PI;
            Settings.Default.ScrewAngleOffset = screwAngleOffset * 180 / Math.PI;

            Settings.Default.IsHypoid     = isHypoid;
            Settings.Default.HypoidAngle  = hypoidAngle * 180 / Math.PI;
            Settings.Default.HypoidOffset = hypoidOffset * lengthConversion;

            Settings.Default.Save();
        }