/// <summary> /// Gets the Y values for which the equation of the circle yields the given X. /// </summary> /// <param name="x">The X value.</param> public decimal[] SolveForY(ref decimal x) { // Alternative calculations. May be faster/more accurate, but need to be tested. //Dim absDiff = Math.Abs(x - _center.X) //Select Case absDiff // Case Is > _radius // Return New Decimal() {} // Case _radius // Return New Decimal() {_center.Y} // Case 0 // Return New Decimal() {_center.Y + _radius, _center.Y - _radius} // Case Else // Dim height = RightTriangle.GetSideFromSideHyp(absDiff, _radius) // Return New Decimal() {_center.Y + height, _center.Y - height} //End Select decimal aCoeff = 0m; decimal bCoeff = 0m; decimal cCoeff = 0m; // Solve for y // (x - h)^2 + (y - k)^2 = r^2 // simplifies to // y^2 - 2 * k * y + k^2 + (x - h)^2 - r^2 = 0 aCoeff = 1; bCoeff = -2 * _center.Y; cCoeff = _center.Y * _center.Y + (x - _center.X) * (x - _center.X) - _radius * _radius; return(DecimalEx.SolveQuadratic(aCoeff, bCoeff, cCoeff)); }
/// <summary> /// Gets the X values for which the equation of the circle yields the given Y. /// </summary> /// <param name="y">The Y value.</param> public decimal[] SolveForX(decimal y) { decimal aCoeff = 0m; decimal bCoeff = 0m; decimal cCoeff = 0m; // Solve for x // (x - h)^2 + (y - k)^2 = r^2 // simplifies to // x^2 - 2 * h * x + h^2 + (y - k)^2 - r^2 = 0 aCoeff = 1; bCoeff = -2 * _center.X; cCoeff = _center.X * _center.X + (y - _center.Y) * (y - _center.Y) - _radius * _radius; return(DecimalEx.SolveQuadratic(aCoeff, bCoeff, cCoeff)); }
/// <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> public Point2D[] GetIntersectFast(ref LineSeg2D l) { decimal[] x = new decimal[2]; decimal m = 0m; decimal b = 0m; decimal aCoeff = 0m; decimal bCoeff = 0m; decimal cCoeff = 0m; decimal lineX = 0m; decimal t = 0m; decimal p = 0m; decimal q = 0m; Point2D[] pts = null; if (!l.IsVertical) { // Circle (x - h) ^ 2 + (y - k) ^ 2 = r ^ 2 // Center: (h, k) // Radius: r // Line y = m * x + b // (x - h) ^ 2 + (m * x + b - k) ^ 2 = r ^ 2 // (x - h) * (x - h) + (m * x + b - k) * (m * x + b - k) = r^2 // (x^2 - 2 * h * x + h^2) + (m^2 * x^2 + 2 * (b - k) * m * x + (b - k)^2 = r^2 // (m^2 + 1) * x^2 + (2 * (b - k) * m - 2 * h) * x + (h^2 + (b - k)^2 - r^2) = 0 m = l.Slope; b = l.YIntersect; aCoeff = DecimalEx.Pow(m, 2) + 1; bCoeff = 2 * (b - _center.Y) * m - 2 * _center.X; cCoeff = DecimalEx.Pow(_center.X, 2) + DecimalEx.Pow(b - _center.Y, 2) - DecimalEx.Pow(_radius, 2); x = DecimalEx.SolveQuadratic(aCoeff, bCoeff, cCoeff); if (x.Length == 0) { return new Point2D[] { } } ; pts = new Point2D[x.Length]; for (var i = 0; i <= x.Length - 1; i++) { pts[i] = new Point2D(x[i], m * x[i] + b); } } else { // Circle (x - h) ^ 2 + (y - k) ^ 2 = r ^ 2 // Center: (h, k) // Radius: r // Line x = lineX // Got the following from // http://www.sonoma.edu/users/w/wilsonst/Papers/Geometry/circles/T1--2/T1-3-2.html // http://www.sonoma.edu/users/w/wilsonst/Papers/Geometry/circles/default.html lineX = l.Pt1.X; t = _radius * _radius - (lineX - _center.X) * (lineX - _center.X); if (t < 0) { return(new Point2D[] { }); } else { p = _center.Y + DecimalEx.Sqrt(t); q = _center.Y - DecimalEx.Sqrt(t); pts = new Point2D[1]; pts[0] = new Point2D(lineX, p); // NOTE that P=Q when t=0 if (p != q) { Array.Resize(ref pts, 2); pts[1] = new Point2D(lineX, q); } } } return(pts); }