public ConnectionLine CalculateBestConnection(Area fromArea, Area destinationArea, Func<Area, ProximityTestResult> isOverlappingWithOtherControls)
        {
            var fromConnectors = GetAllConnectorPoints(fromArea, false);
            var toLineEndConnectors = GetAllConnectorPoints(destinationArea, true);
            var toArrowTipConnectors = GetAllConnectorPoints(destinationArea, false);
            // Logger.Instance.WriteEntry("Finding Best Connection Line from {0} to {1}", (fromArea.Tag ?? fromArea.TopLeft.ToString()), (destinationArea.Tag ?? destinationArea.TopLeft.ToString()));
            // Logger.Instance.WriteEntry("    From: {0}  To: {1}", fromArea, destinationArea);

            double angle = fromArea.Centre.AngleToPointInDegrees(destinationArea.Centre);
            var idealPoint = fromArea.CalculateCircumferenceIntersectionPoint(angle);
            var chosenfromConnector = fromConnectors.Select(fromConnector => new Tuple<KeyValuePair<int, Point>, double>(fromConnector, fromConnector.Value.DistanceTo(idealPoint)))
                .OrderBy(x => x.Item2)
                .First();
            var toConnectorsInOrderOfPreference = toLineEndConnectors.Select(toConnector => new Tuple<KeyValuePair<int, Point>, double>(toConnector, toConnector.Value.DistanceTo(idealPoint)))
                .OrderBy(x => x.Item2)
                .ToList();

            // This code checks to see if the arrow head is overlapping with an existing diagram element. (not really needed)
            //int chosenToIndex = 0;
            //for (int toConnectorIndex = 0; toConnectorIndex < toConnectors.Length; toConnectorIndex++)
            //{
            //    var toConnector = toConnectorsInOrderOfPreference[toConnectorIndex];
            //    Area arrowheadArea = ArrowHead.GetArea(CalculateExitAngle(toConnectorIndex), toConnector.Item1);
            //    ProximityTestResult proximityTestResult = isOverlappingWithOtherControls(arrowheadArea);
            //    if (proximityTestResult.Proximity == Proximity.NotOverlapping || proximityTestResult.Proximity == Proximity.VeryClose)
            //    {
            //        chosenToIndex = toConnectorIndex;
            //        break;
            //    }
            //}

            return new ConnectionLine
                {
                    Distance = chosenfromConnector.Item1.Value.DistanceTo(toConnectorsInOrderOfPreference[0].Item1.Value),
                    From = chosenfromConnector.Item1.Value,
                    To = toArrowTipConnectors[toConnectorsInOrderOfPreference[0].Item1.Key], // toConnectorsInOrderOfPreference[0].Item1.Value, // Incorrect
                    ToLineEnd = toConnectorsInOrderOfPreference[0].Item1.Value,
                    ExitAngle = CalculateExitAngle(toConnectorsInOrderOfPreference[0].Item1.Key)
                };
        }
        /// <summary>
        /// Calculate the best line connecting <see cref="fromArea"/> to <see cref="destinationArea"/>
        /// </summary>
        /// <param name="fromArea">
        /// The from Area.
        /// </param>
        /// <param name="destinationArea">
        /// The destination Area.
        /// </param>
        /// <param name="isOverlappingWithOtherControls">
        /// The is Overlapping With Other Controls.
        /// </param>
        /// <returns>
        /// The <see cref="ConnectionLine"/>.
        /// </returns>
        public ConnectionLine CalculateBestConnection(Area fromArea, Area destinationArea, Func<Area, ProximityTestResult> isOverlappingWithOtherControls)
        {
            double fromAngle = fromArea.Centre.AngleToPointInDegrees(destinationArea.Centre);
            Point fromIdealPoint = fromArea.CalculateCircumferenceIntersectionPoint(fromAngle);
            double toAngle = TrigHelper.InverseAngle(fromAngle);
            Point toIdealPoint = destinationArea.CalculateCircumferenceIntersectionPoint(toAngle);
            Point toLineEnd = toIdealPoint;

            // Leave room for arrow head
            double offset1 = (ArrowHead.ArrowWidth - 2) * Math.Sin(CalculateLineAngleToPreviousAxis(toAngle));
            double offset2 = (ArrowHead.ArrowWidth - 2) * Math.Cos(CalculateLineAngleToPreviousAxis(toAngle));
            if (toAngle >= 0 && toAngle < 90)
            {
                toLineEnd.Offset(offset1, -offset2);
            }
            else if (toAngle >= 90 && toAngle <= 180)
            {
                toLineEnd.Offset(offset2, offset1);
            }
            else if (toAngle > 180 && toAngle < 270)
            {
                toLineEnd.Offset(-offset1, offset2);
            }
            else
            {
                toLineEnd.Offset(-offset2, -offset1);
            }

            return new ConnectionLine
                {
                    Distance = fromIdealPoint.DistanceTo(toIdealPoint),
                    ExitAngle = CalculateExitAngle(fromAngle),
                    From = fromIdealPoint,
                    To = toIdealPoint,
                    ToLineEnd = toLineEnd,
                    ToAngle = toAngle,
                    FromAngle = fromAngle,
                };
        }