/// <summary> /// Attempt to find convexity-sensitive angle between the normals of the adjacent faces of an edge using its midpoint. Returns a negavive angle for concave edges, 0 for tangent, or postitive for convex. /// </summary> /// <param name="edge">The Edge who's convexity is to be determined.</param> /// <returns></returns> public static double GetAngle(this Edge edge) { if (edge.Fins.Count != 2) { throw new ArgumentException("Edge must have two fins in order to have angle."); } CurveEvaluation curveEval = edge.Geometry.Evaluate((edge.Bounds.Start + edge.Bounds.End) / 2); Point edgePoint = curveEval.Point; Direction tangent = curveEval.Tangent; Fin finA = edge.Fins.ToArray()[0]; if (finA.IsReversed ^ finA.Edge.IsReversed) { tangent = -tangent; } Direction dirA = finA.Loop.Face.ProjectPoint(edgePoint).Normal; if (finA.Loop.Face.IsReversed) { dirA = -dirA; } Fin finB = edge.Fins.ToArray()[1]; Direction dirB = finB.Loop.Face.ProjectPoint(edgePoint).Normal; if (finB.Loop.Face.IsReversed) { dirB = -dirB; } double sense = Math.Asin(Math.Min(Math.Max(Vector.Dot(Direction.Cross(tangent, dirA).UnitVector, dirB.UnitVector), -1), 1)); // can be slightly out of range of [-1 ,1] if (Accuracy.AngleIsZero(sense)) { return(0); } return(Math.Abs(AddInHelper.AngleBetween(dirA, dirB)) * (sense > 0 ? 1 : -1)); }
private Body CreateGearBody() { int numSteps = (int)Math.Max(Math.Ceiling(Math.Abs(64 * HelixRotations / 2 / Math.PI) + 1), 2); if (this is BevelGear /*|| this is HypoidGear*/) { numSteps *= 4; } int extraSteps = 2; if (Accuracy.AngleIsZero(TotalTwistAngle)) { numSteps = 2; extraSteps = 0; //0 } double accuracy = Accuracy.LinearResolution; // Period.Print(); var orderedCurveChain = new TrimmedCurveChain(Period); orderedCurveChain.Reverse(); IList <ITrimmedCurve> orderedCurves = orderedCurveChain.SortedCurves; var periodBodies = new List <Body>(); foreach (ITrimmedCurve iTrimmedCurve in orderedCurves) { var profiles = new List <ICollection <ITrimmedCurve> >(); for (int i = -extraSteps; i < numSteps + extraSteps; i++) { ITrimmedCurve transformedCurve = GetTransformedProfileCurve(iTrimmedCurve, (double)i / (numSteps - 1)); var profile = new List <ITrimmedCurve>(); profile.Add(transformedCurve); profiles.Add(profile); } try { periodBodies.Add(Body.LoftProfiles(profiles, false, false)); } catch { foreach (ICollection <ITrimmedCurve> curves in profiles) { foreach (ITrimmedCurve curve in curves) { DesignCurve.Create(Part, curve); } } } } Body periodBody = periodBodies.TryUnionOrFailBodies(); var profileBodies = new List <Body>(); var startProfile = new List <ITrimmedCurve>(); var endProfile = new List <ITrimmedCurve>(); Matrix trans; for (int i = 0; i < GearData.NumberOfTeeth; i++) { trans = Matrix.CreateRotation(Line.Create(Point.Origin, Direction.DirZ), GearData.PitchAngle * 2 * i); profileBodies.Add(periodBody.CreateTransformedCopy(trans)); } Body gearBody = profileBodies.TryUnionAndStitchOrFailBodies(); Body cappingBody = GetCappingBody(); try { // throw new NotImplementedException(); if (GearData.IsInternal) { // gearBody.Subtract(new Body[] { cappingBody }); cappingBody.Subtract(new Body[] { gearBody }); gearBody = cappingBody; } else { gearBody.Intersect(new Body[] { cappingBody }); } } catch { DesignBody.Create(Part, "capping", cappingBody.Copy()); DesignBody.Create(Part, "gear", gearBody.Copy()); } return(gearBody); }