/// <summary> /// Gets the angle in degrees for a ray that extends from the center /// of the circle through the given point. An exception will occur, /// however, if the point specified is the same point as the center /// of the circle. /// </summary> /// <param name="pt">The point.</param> public decimal AngleThroughPoint(Point2D pt) { decimal a = 0m; // Shift point so it's relative to the origin. pt += new Vector2D(-Center.X, -Center.Y); // Do check here after we've translated the point // to account for small precision rounding. if (pt == Point2D.Origin) { throw new Exception("No angle through given point since point is at center of circle!"); } // Special case for 0 and 180 where we would get // a divide by zero below. if (pt.Y == 0) { if (pt.X > 0) { return(0); } else { return(180); } } // Special case for 90 and 270 where we can't // determine quadrant below. if (pt.X == 0) { if (pt.Y > 0) { return(90); } else { return(270); } } a = DecimalEx.ToDeg(DecimalEx.ATan(pt.X / pt.Y)); switch (pt.Quadrant) { case 1: case 2: a = 90 - a; break; case 3: case 4: a = 270 - a; break; } return(a); }
/// <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 angle in degrees from the two known sides. /// </summary> /// <param name="oppositeSide">Length of the known side opposite the angle.</param> /// <param name="adjacentSide">Length of the known side adjacent to the angle.</param> public static decimal GetAngleFromSides(decimal oppositeSide, decimal adjacentSide) { // tan(a) = opposideSide / adjacentSide // a = atan(opposideSide / adjacentSide) return(DecimalEx.ToDeg(DecimalEx.ATan(oppositeSide / adjacentSide))); }