private static Line ClosestLine(Rect rect, Point p)
        {
            var angle = new Vector(1, 1).AngleTo(p.VectorTo(rect.CenterPoint()));
            if (angle >= 0 && angle <= 90)
            {
                return rect.TopLine();
            }

            if (angle >= 90 && angle <= 180)
            {
                return rect.RightLine();
            }

            if (angle >= -90 && angle <= 0)
            {
                return rect.LeftLine();
            }

            if (angle >= -180 && angle <= -90)
            {
                return rect.BottomLine();
            }

            throw new InvalidOperationException("Could not find closest line");
        }
        private Point? GetPointOnTarget(Point sourceMidPoint, Rect target)
        {
            switch (this.Vertical)
            {
                case VerticalPlacement.Auto:
                    switch (this.Horizontal)
                    {
                        case HorizontalPlacement.Auto:
                            var closestLine = ClosestLine(target, sourceMidPoint);
                            return AutoPoint(sourceMidPoint.LineTo(target.CenterPoint()), closestLine);
                        case HorizontalPlacement.Left:
                            return AutoPoint(sourceMidPoint.LineTo(target.CenterPoint()), target.LeftLine());
                        case HorizontalPlacement.Center:
                            return sourceMidPoint.Closest(target.BottomLine(), target.TopLine())
                                                 .MidPoint;
                        case HorizontalPlacement.Right:
                            return AutoPoint(sourceMidPoint.LineTo(target.CenterPoint()), target.RightLine());
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                case VerticalPlacement.Top:
                    switch (this.Horizontal)
                    {
                        case HorizontalPlacement.Auto:
                            return AutoPoint(sourceMidPoint.LineTo(target.CenterPoint()), target.TopLine());
                        case HorizontalPlacement.Left:
                            return target.TopLeft;
                        case HorizontalPlacement.Center:
                            return PointExt.MidPoint(target.TopLeft, target.TopRight);
                        case HorizontalPlacement.Right:
                            return target.TopRight;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                case VerticalPlacement.Center:
                    switch (this.Horizontal)
                    {
                        case HorizontalPlacement.Auto:
                            return sourceMidPoint.Closest(target.LeftLine(), target.RightLine())
                                                 .MidPoint;
                        case HorizontalPlacement.Left:
                            return PointExt.MidPoint(target.BottomLeft, target.TopLeft);
                        case HorizontalPlacement.Center:
                            return PointExt.MidPoint(target.TopLeft, target.BottomRight);
                        case HorizontalPlacement.Right:
                            return PointExt.MidPoint(target.BottomRight, target.TopRight);
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                case VerticalPlacement.Bottom:
                    switch (this.Horizontal)
                    {
                        case HorizontalPlacement.Auto:
                            return AutoPoint(sourceMidPoint.LineTo(target.CenterPoint()), target.BottomLine());
                        case HorizontalPlacement.Left:
                            return target.BottomLeft;
                        case HorizontalPlacement.Center:
                            return PointExt.MidPoint(target.BottomLeft, target.BottomRight);
                        case HorizontalPlacement.Right:
                            return target.BottomRight;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
Пример #3
0
        internal Point? FirstIntersectionWith(Rect rectangle)
        {
            var quadrant = rectangle.Contains(this.Point)
                ? this.Direction.Quadrant()
                : this.Direction.Negated().Quadrant();

            switch (quadrant)
            {
                case Quadrant.NegativeXPositiveY:
                    return IntersectionPoint(this, rectangle.LeftLine(), true) ??
                           IntersectionPoint(this, rectangle.BottomLine(), true);
                case Quadrant.PositiveXPositiveY:
                    return IntersectionPoint(this, rectangle.RightLine(), true) ??
                           IntersectionPoint(this, rectangle.BottomLine(), true);
                case Quadrant.PositiveXNegativeY:
                    return IntersectionPoint(this, rectangle.RightLine(), true) ??
                           IntersectionPoint(this, rectangle.TopLine(), true);
                case Quadrant.NegativeXNegativeY:
                    return IntersectionPoint(this, rectangle.LeftLine(), true) ??
                           IntersectionPoint(this, rectangle.TopLine(), true);
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }