private static Point FindTangentPoint(Ray ray, Rect rectangle, CornerRadius cornerRadius) { var toMid = ray.PerpendicularLineTo(rectangle.CenterPoint()); Debug.Assert(toMid != null, "Cannot find tangent if line goes through center"); if (toMid == null) { // failing silently in release return(rectangle.CenterPoint()); } //Debug.Assert(!rectangle.Contains(toMid.Value.StartPoint), "Cannot find tangent if line intersects rectangle"); if (toMid.Value.Direction.Axis() != null) { return(ray.Point.Closest(rectangle.TopLeft, rectangle.TopRight, rectangle.BottomRight, rectangle.BottomLeft)); } Circle corner; switch (toMid.Value.Direction.Quadrant()) { case Quadrant.NegativeXPositiveY: corner = CreateTopRight(rectangle.TopRight, cornerRadius.TopRight); break; case Quadrant.PositiveXPositiveY: corner = CreateTopLeft(rectangle.TopLeft, cornerRadius.TopLeft); break; case Quadrant.PositiveXNegativeY: corner = CreateBottomLeft(rectangle.BottomLeft, cornerRadius.BottomLeft); break; case Quadrant.NegativeXNegativeY: corner = CreateBottomRight(rectangle.BottomRight, cornerRadius.BottomRight); break; default: throw new ArgumentOutOfRangeException(); } // ReSharper disable once CompareOfFloatsByEqualityOperator if (corner.Radius == 0) { return(corner.Center); } var lineToCenter = ray.PerpendicularLineTo(corner.Center); Debug.Assert(lineToCenter != null, "Ray cannot go through center here"); if (lineToCenter == null) { // this should never happen but failing silently // the balloons should not throw much. return(corner.Center); } return(corner.Center - corner.Radius * lineToCenter.Value.Direction); }
private static Point FindTangentPoint(Ray toCenter, Ellipse ellipse) { var toEllipseCenter = toCenter.PerpendicularLineTo(ellipse.Center); Debug.Assert(toEllipseCenter != null, "Ray should not go through ellipse center here"); if (toEllipseCenter == null) { // this should never happen but failing silently // the balloons should not throw much returning random point. return(ellipse.Center); } return(ellipse.PointOnCircumference(toEllipseCenter.Value.Direction.Negated())); }
private static Point FindTangentPoint(Ray toCenter, Ellipse ellipse) { var toEllipseCenter = toCenter.PerpendicularLineTo(ellipse.CenterPoint); Debug.Assert(toEllipseCenter != null, "Ray should not go through ellipse center here"); if (toEllipseCenter == null) { // this should never happen but failing silently // the balloons should not throw much returning random point. return ellipse.CenterPoint; } return ellipse.PointOnCircumference(toEllipseCenter.Value.Direction.Negated()); }
private static Point FindTangentPoint(Ray ray, Rect rectangle, CornerRadius cornerRadius) { var toMid = ray.PerpendicularLineTo(rectangle.CenterPoint()); Debug.Assert(toMid != null, "Cannot find tangent if line goes through center"); if (toMid == null) { // failing silently in release return rectangle.CenterPoint(); } // Debug.Assert(!rectangle.Contains(toMid.Value.StartPoint), "Cannot find tangent if line intersects rectangle"); if (toMid.Value.Direction.Axis() != null) { return ray.Point.Closest(rectangle.TopLeft, rectangle.TopRight, rectangle.BottomRight, rectangle.BottomLeft); } Circle corner; switch (toMid.Value.Direction.Quadrant()) { case Quadrant.NegativeXPositiveY: corner = CreateTopRight(rectangle.TopRight, cornerRadius.TopRight); break; case Quadrant.PositiveXPositiveY: corner = CreateTopLeft(rectangle.TopLeft, cornerRadius.TopLeft); break; case Quadrant.PositiveXNegativeY: corner = CreateBottomLeft(rectangle.BottomLeft, cornerRadius.BottomLeft); break; case Quadrant.NegativeXNegativeY: corner = CreateBottomRight(rectangle.BottomRight, cornerRadius.BottomRight); break; default: throw new ArgumentOutOfRangeException(); } // ReSharper disable once CompareOfFloatsByEqualityOperator if (corner.Radius == 0) { return corner.Center; } var lineToCenter = ray.PerpendicularLineTo(corner.Center); Debug.Assert(lineToCenter != null, "Ray cannot go through center here"); if (lineToCenter == null) { // this should never happen but failing silently // the balloons should not throw much. return corner.Center; } return corner.Center - corner.Radius * lineToCenter.Value.Direction; }