/// <summary> /// Calculates callout balloon vertexes suitable for curve drawing /// </summary> /// <param name="body">Balloon body coordinates</param> /// <param name="target">A point of balloon leg attachment</param> /// <param name="legSweep">Length of balloon leg attachment breach at balloon body edge, expressed in radians (arc length). A value such as PI/16 yields good results</param> /// <returns>An array of vertex points</returns> public static Point[] VectorizeBalloon(Rectangle body, Point target, double legSweep) { List <Point> result = new List <Point>(); Point center = new Point(body.Left + body.Width / 2, body.Top + body.Height / 2); PolarPoint trg = new PolarPoint(center, target); Point legStart = CartesianUtils.FindRayFromRectangleCenterSideIntersection( body, CartesianUtils.WrapAngle(trg.Theta, -legSweep / 2)); Point legEnd = CartesianUtils.FindRayFromRectangleCenterSideIntersection( body, CartesianUtils.WrapAngle(trg.Theta, +legSweep / 2)); result.Add(new Point(body.Left, body.Top)); result.Add(new Point(body.Right, body.Top)); result.Add(new Point(body.Right, body.Bottom)); result.Add(new Point(body.Left, body.Bottom)); result.Add(legStart); result.Add(target); result.Add(legEnd); //reorder points by azimuth so the curve can close and look like a balloon result.Sort((p1, p2) => { PolarPoint pp1 = new PolarPoint(center, p1); PolarPoint pp2 = new PolarPoint(center, p2); if (pp1.Theta > pp2.Theta) { return(-1); } else { return(+1); } }); return(result.ToArray()); }
/// <summary> /// Initializes polar coordinates from 2-d cartesian coordinates of 'x1, y1, x2, y2' format /// </summary> public PolarPoint(int x1, int y1, int x2, int y2) { this = CartesianUtils.VectorToPolarPoint(x1, y1, x2, y2); }
/// <summary> /// Initializes polar coordinates from 2-d cartesian coordinates /// </summary> public PolarPoint(Point center, Point point) { this = CartesianUtils.PointToPolarPoint(center, point); }