예제 #1
0
        /// <summary>
        /// Inflates balloon body and target point
        /// </summary>
        public static void InflateBalloon(ref Rectangle body, ref Point target, int deltaBody, int deltaTarget)
        {
            Point      center = new Point(body.Left + body.Width / 2, body.Top + body.Height / 2);
            PolarPoint pp     = new PolarPoint(center, target);

            body.Inflate(deltaBody, deltaBody);

            pp.R += deltaTarget;

            target = pp.Point;
            target.Offset(center.X, center.Y);
        }
예제 #2
0
        /// <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());
        }
예제 #3
0
        /// <summary>
        /// Returns a point of intersection between a ray cast from the center of a rectangle
        ///  under certain polar coordinate angle and a rectangle side
        /// </summary>
        public static Point FindRayFromRectangleCenterSideIntersection(Rectangle rect, double theta)
        {
            Point center = new Point(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);

            double rayLength = rect.Width > rect.Height ? rect.Width : rect.Height; //make ray "infinite" in comparison to rect

            if (rayLength < 100)
            {
                rayLength = 100;                                                                       //safeguard
            }
            PolarPoint rayEnd = new PolarPoint(rayLength, theta);                                      //create ray "end" point

            double k = (rayEnd.Point.X != 0)? ((double)rayEnd.Point.Y) / ((double)rayEnd.Point.X) : 0; //get line incline  aka. y = kx

            int x, y;

            List <Point> lst = new List <Point>();

            //north
            x = center.X + ((k != 0) ? (int)((rect.Top - center.Y) / k) : 0);
            y = rect.Top;
            if ((x >= rect.Left) &&
                (x <= rect.Right))
            {
                lst.Add(new Point(x, y));
            }

            //south
            x = center.X + ((k != 0) ? (int)((rect.Bottom - center.Y) / k) : 0);
            y = rect.Bottom;
            if ((x >= rect.Left) &&
                (x <= rect.Right))
            {
                lst.Add(new Point(x, y));
            }

            //east
            x = rect.Right;
            y = center.Y + (int)(k * (rect.Right - center.X));
            if ((y >= rect.Top) &&
                (y <= rect.Bottom))
            {
                lst.Add(new Point(x, y));
            }

            //west
            x = rect.Left;
            y = center.Y + (int)(k * (rect.Left - center.X));
            if ((y >= rect.Top) &&
                (y <= rect.Bottom))
            {
                lst.Add(new Point(x, y));
            }

            Point minPoint    = new Point(int.MaxValue, int.MaxValue);
            int   minDistance = int.MaxValue;

            Point re = rayEnd.Point;       //rayEnd is relative to absolute 0,0

            re.Offset(center.X, center.Y); // need to make relative to rectangle center

            foreach (Point p in lst)       //find closest point
            {
                int dst = Distance(p, re);

                if (dst < minDistance)
                {
                    minPoint    = p;
                    minDistance = dst;
                }
            }

            return(minPoint);
        }