/// <summary>
        /// Constructor
        /// The Routing map is initialised with HardBlocks covering the shapes.
        /// It is also necessary to call MapConnectors() to initialise the RoutedPoints Dictionary with the existing connections.
        /// </summary>
        /// <param name="model"></param>
        public ConnectionRouter(Model model)
        {
            routingSpace = View.RoundOutToGrid(model.GetDiagramBounds(RoutingMargin));

            // Create the map of routing points on the grid spacing
            map = new RouteMap(routingSpace.Width / View.GRID_SIZE, routingSpace.Height / View.GRID_SIZE);

            foreach (var task in Model.Workflow.Tasks)
            {
                var shape  = task.Symbol.Shape;
                var bounds = View.RoundOutToGrid(shape.Bounds);
                bounds.X -= routingSpace.X;
                bounds.Y -= routingSpace.Y;
                for (var x = bounds.Left / 10; x <= bounds.Right / 10; x++)
                {
                    for (var y = bounds.Top / 10; y <= bounds.Bottom / 10; y++)
                    {
                        map[x, y] = RouteState.HardBlock;
                    }
                }

                // Make holes
                foreach (var pin in shape.pins.Values)
                {
                    var m = SnapToMap(shape.Bounds.X + pin.Centre.X, shape.Bounds.Y + pin.Centre.Y);
                    while (map.Inside(m) && map[m] == RouteState.HardBlock)
                    {
                        map[m] = RouteState.Empty;
                        m      = m.Step(pin.Direction);
                    }
                }
            }
        }