/// <summary>
        /// Route a single connection
        /// </summary>
        /// <param name="conn"></param>
        /// <returns></returns>
        public bool RouteConnection(Connector conn)
        {
            Debug.WriteLine("Connecting {0}:{1} to {2}:{3}", conn.TaskFrom.TaskId, conn.Flow.Name, conn.Flow.Target, conn.Flow.TargetPin);

            var start = SnapToMap(conn.TaskFrom.Symbol.Shape.Bounds.X + conn.PinFrom.Centre.X, conn.TaskFrom.Symbol.Shape.Bounds.Y + conn.PinFrom.Centre.Y);

            target = SnapToMap(conn.TaskTo.Symbol.Shape.Bounds.X + conn.PinTo.Centre.X, conn.TaskTo.Symbol.Shape.Bounds.Y + conn.PinTo.Centre.Y);
            Debug.WriteLine("Coordinates ({0}, {1}) to ({2}, {3})", start.X, start.Y, target.X, target.Y);
            map.ClearVisitedFlags();
            queue       = new PriorityQueue(200);
            routePoints = new Dictionary <MapRef, RoutePoint>();
            var initial = new RoutePoint(start.X, start.Y)
            {
                Direction = conn.PinFrom.Direction,
                Heuristic = Manhatten(start, target)
            };

            queue.Enqueue(initial);

            RoutePoint route = null;

            while (route == null)
            {
                if (queue.Count == 0)
                {
                    Debug.WriteLine("FAILED TO CONNECT {0}:{1} to {2}:{3}", conn.TaskFrom.TaskId, conn.Flow.Name, conn.Flow.Target, conn.Flow.TargetPin);
                    return(false);
                }
                route = Astar();
            }

            var connectorPoints = new List <Point>();

            var trace = route;

            connectorPoints.Add(MapToDiagram(trace.X, trace.Y));
            while (trace != null)
            {
                AddRoutedPoint(trace.Location, target, trace.Direction);

                if (trace.Previous == null)
                {
                    connectorPoints.Add(MapToDiagram(trace.X, trace.Y));
                }
                else if (trace.Previous.Direction != trace.Direction)
                {
                    connectorPoints.Add(MapToDiagram(trace.Previous.X, trace.Previous.Y));
                }

                trace = trace.Previous;
            }
            connectorPoints.Reverse();
            conn.Points = connectorPoints;
            return(true);
        }
        /// <summary>
        /// Interpolate over [from, to) in the map
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        private static IEnumerable <MapRef> Interpolate(MapRef from, MapRef to)
        {
            var dir = Direction.Create(from, to);


            var i = from;

            while (i.X != to.X || i.Y != to.Y)
            {
                // Debug.WriteLine("MapRef = {0}, {1}", i.X, i.Y);
                yield return(i);

                i = i.Step(dir);
            }
        }
 /// <summary>
 /// Create a direction between two orthogonal points
 /// </summary>
 /// <param name="from"></param>
 /// <param name="to"></param>
 /// <returns></returns>
 public static Direction Create(MapRef from, MapRef to)
 {
     if (from == to)
     {
         throw new ApplicationException("Direction - points equal");
     }
     if (from.X == to.X)
     {
         return(to.Y > from.Y ? South : North);
     }
     if (from.Y == to.Y)
     {
         return(to.X > from.X ? East : West);
     }
     throw new ApplicationException("Direction - points not aligned");
 }
        private void AddRoutedPoint(MapRef m, MapRef targ, Direction dir)
        {
            RoutedPoint routedPoint;

            if (routedPoints.TryGetValue(m, out routedPoint))
            {
                if (routedPoint.Target != targ)
                {
                    routedPoints[m] = new RoutedPoint();       // RoutedPoint cross (different targets)
                }
                else if (routedPoint.Direction != dir)
                {
                    routedPoints[m] = new RoutedPoint(targ);   // RoutedPoint join (same target from different directions)
                }
            }
            else
            {
                routedPoints[m] = new RoutedPoint(targ, dir);
            }
        }
 /// <summary>
 /// Test if a MapRef lies within the extents of this RouteMap
 /// </summary>
 /// <param name="m"></param>
 /// <returns></returns>
 public bool Inside(MapRef m)
 {
     return(m.X >= 0 && m.Y >= 0 && m.X < Width && m.Y < Height);
 }
 /// <summary>
 /// Get the RouteState of a MapRef in this RouteMap
 /// </summary>
 /// <param name="mr"></param>
 /// <returns></returns>
 public RouteState this[MapRef mr]
 {
     get { return(this[mr.X, mr.Y]); }
     set { this[mr.X, mr.Y] = value; }
 }
 /// <summary>
 /// Manhatten distance (Distance a rook moves on a chessboard)
 /// </summary>
 /// <param name="from"></param>
 /// <param name="to"></param>
 /// <returns></returns>
 private int Manhatten(MapRef from, MapRef to)
 {
     return(Math.Abs(from.X - to.X) + Math.Abs(from.Y - to.Y));
 }