/// <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)); }