/// <summary> /// Returns the sagitta (the distance between the highest point of /// an arc and the center of the chord) for a circle with the /// supplied radius the chord length. /// </summary> /// <param name="radius">The radius of the circle.</param> /// <param name="chordLength"> /// The distance between the two endpoints of the chord. /// </param> public static decimal GetSagitta(decimal radius, decimal chordLength) { // s = r - sqrt(r^2 - l^2) // where r = radius // l = 1/2 chord length return(radius - RightTriangle.GetSideFromSideHyp(chordLength / 2, radius)); }
/// <summary> /// Returns a line segment with the coordinates of a chord centered on /// the given angle with the given length. /// </summary> /// <param name="angleThroughCenter">The angle that passes through the /// center of the chord, in degrees.</param> /// <param name="chordLength">The length of the chord.</param> public LineSeg2D GetChord(decimal angleThroughCenter, decimal chordLength) { LineSeg2D l = default(LineSeg2D); decimal a = 0m; // Create a right triangle where one side is half the chord length, // the other side is from the center of the circle to the midpoint // of the chord, and the hypotenuse is from the center of the circle // to the chord start point a = RightTriangle.GetAngleFromOppSideHyp(0.5m * chordLength, _radius); l.Pt1 = PointAt(angleThroughCenter - a); l.Pt2 = PointAt(angleThroughCenter + a); return(l); }
/// <summary> /// Gets the total angle on a circle of the given radius from one side of the chord to the other. /// </summary> /// <param name="chordLength">The length of the chord.</param> /// <param name="circleRadius">The radius of the circle.</param> public static decimal GetChordTotalAngle(decimal chordLength, decimal circleRadius) { if (chordLength == 0) { return(0m); } else if (chordLength > circleRadius * 2m) { throw new Exception("Chord can't fit inside a circle with the specified radius!"); } else if (chordLength == circleRadius * 2m) { return(180m); } else { return(RightTriangle.GetAngleFromOppSideHyp(0.5m * chordLength, circleRadius) * 2m); } }
/// <summary> /// Gets a line segment of length 1 starting at the point on the circle /// and extending either clockwise or counterclockwise. /// </summary> /// <param name="degrees">An angle.</param> public LineSeg2D TangentAt(decimal degrees, decimal length, bool clockwise) { var r = RightTriangleAbstract.FromTwoSides(_radius, length); decimal rad = DecimalEx.ToRad(degrees + r.AngleA); LineSeg2D ret = default(LineSeg2D); Debug.Assert(r.AngleA == RightTriangle.GetAngleFromSides(length, _radius)); Debug.Assert(r.Hypotenuse == RightTriangle.GetHypFromSides(length, _radius)); ret.Pt1 = PointAt(degrees); if (!clockwise) { ret.Pt2 = new Point2D(_center.X + r.Hypotenuse * DecimalEx.Cos(rad), _center.Y + r.Hypotenuse * DecimalEx.Sin(rad)); } else { ret.Pt2 = new Point2D(ret.Pt1.X - (_center.X + r.Hypotenuse * DecimalEx.Cos(rad) - ret.Pt1.X), ret.Pt1.Y - (_center.Y + r.Hypotenuse * DecimalEx.Sin(rad) - ret.Pt1.Y)); } return(ret); }
public static Circle2D[] FromTwoPointsAndRadius(decimal x1, decimal y1, decimal x2, decimal y2, decimal radius) { LineSeg2D pointToPoint = default(LineSeg2D); Point2D midPoint = default(Point2D); Vector2D vPerpBisector = default(Vector2D); if (x1 == x2 && y1 == y2) { return new Circle2D[] { } } ; pointToPoint = new LineSeg2D(x1, y1, x2, y2); midPoint = pointToPoint.MidPoint; vPerpBisector = pointToPoint.PerpendicularBisector().GetVectorP1toP2(); vPerpBisector.Magnitude = RightTriangle.GetSideFromSideHyp(pointToPoint.Length / 2, radius); return(new Circle2D[] { new Circle2D(midPoint + vPerpBisector, radius), new Circle2D(midPoint - vPerpBisector, radius) }); }
/// <summary> /// Gets the chamfer drop along a given angle for a given distance. /// </summary> /// <param name="chamferDistance">The length of the chamfer.</param> /// <param name="chamferAngle">The angle of the chamfer in degrees.</param> public static decimal GetChamferDrop(decimal chamferDistance, decimal chamferAngle) { return(RightTriangle.GetSideFromOppAngleOppSide(chamferAngle, chamferDistance)); }
/// <summary> /// Gets the points of intersection between this circle and the line which /// contains the given line segment. /// </summary> /// <param name="l">Line segment used to determine line equation.</param> /// <param name="decimals">Determines rounding that should be performed when determining /// if line intersection happens on zero, one, or two points. Default is -1 for /// no rounding.</param> public Point2D[] GetIntersect(LineSeg2D l, int decimals = -1) { LineSeg2D centToLine = default(LineSeg2D); decimal centToLineLength = 0m; decimal centToLineLengthForComp = 0m; decimal radiusForComp = 0m; if (l.IsHorizontal) { // The center to any horizontal line is a vertical line through // the center of the circle. centToLine = new LineSeg2D(this.Center, this.Center + new Vector2D(0, 1)); } else { centToLine = LineSeg2D.FromPointSlope(this.Center, l.PerpendicularSlope); } centToLine.Pt2 = l.GetIntersect(centToLine, true).Value; centToLineLength = centToLine.Length; // Get numbers for comparison, rounding if necessary centToLineLengthForComp = centToLineLength; radiusForComp = _radius; if (decimals >= 0) { centToLineLengthForComp = centToLineLengthForComp.RoundFromZero(decimals); radiusForComp = radiusForComp.RoundFromZero(decimals); } // See if line is outside of circle if (centToLineLengthForComp > radiusForComp) { return(new Point2D[] { }); } // See if line is tangent to circle if (centToLineLengthForComp == radiusForComp) { return(new Point2D[] { centToLine.Pt2 }); } // Line must intersect in two places Vector2D vCentToChord = default(Vector2D); decimal halfChord = 0m; // Get a vector from the center to the intersecting chord vCentToChord = centToLine.GetVectorP1toP2(); if (vCentToChord.Magnitude == 0) { Vector2D offsetVector = default(Vector2D); // Line goes through circle center if (l.IsVertical) { // Slope undefined so just go up the length of the radius offsetVector = new Vector2D(0, _radius); } else { offsetVector = new Vector2D(_radius * DecimalEx.Cos(DecimalEx.ATan(l.Slope)), _radius * DecimalEx.Sin(DecimalEx.ATan(l.Slope))); } return(new Point2D[] { this.Center + offsetVector, this.Center - offsetVector }); } else { Vector2D vChord = default(Vector2D); // Get a vector along the chord vChord = vCentToChord.GetPerpendicular(); // Determine the length of half the chord halfChord = RightTriangle.GetSideFromSideHyp(centToLineLength, _radius); // Set the magnitude of the vector along the chord // to be half the chord length vChord.Magnitude = halfChord; // The two intersecting points are points translated // from the center of the circle to the chord (+vCentToChord) // and then translated to the ends of the chord (+-vChord) return(new Point2D[] { this.Center + vCentToChord + vChord, this.Center + vCentToChord - vChord }); } }
/// <summary> /// Gets the chord length for the sagitta and radius. /// </summary> public static decimal GetChordLengthFromRadiusSagitta(decimal radius, decimal sagitta) { return(2 * RightTriangle.GetSideFromSideHyp(radius - sagitta, radius)); }