public RoomControl(Room room, int numRows, double sw, double sh)
        {
            _numRows = numRows;
            _sw = sw;
            _sh = sh;

            InitializeComponent();

            var insideEdges = new List<Coords>();
            var outsideEdges = new List<Coords>();

            foreach (var cell in room.Cells)
            {
                var rect = new Rect(cell.Col * _sw, (_numRows - cell.Row - 1) * _sh, _sw, _sh);
                var rectangle = new Rectangle { Width = rect.Width, Height = rect.Height };
                Canvas.SetLeft(rectangle, rect.Left);
                Canvas.SetTop(rectangle, rect.Top);
                rectangle.Fill = new SolidColorBrush(_cellColour);
                RoomCanvas.Children.Add(rectangle);
                DetermineEdges(insideEdges, outsideEdges, room.Cells, cell.Col, cell.Row);
            }

            // TODO: we should probably de-dup insideEdges.
            // e.g. [(1, 1), (1, 0), (1, 0), (1, 1)] => [(1, 1), (1, 0)]
            var insideEdgeLinePoints = CalculateEdgeLinePoints(insideEdges);
            for (var i = 0; i < insideEdgeLinePoints.Count/2; i++)
            {
                var pt1 = insideEdgeLinePoints[i * 2];
                var pt2 = insideEdgeLinePoints[i * 2 + 1];
                var line = new Line
                {
                    X1 = pt1.X,
                    Y1 = pt1.Y,
                    X2 = pt2.X,
                    Y2 = pt2.Y,
                    Stroke = new SolidColorBrush(_innerCellLineColour),
                    StrokeThickness = InnerCellLineWidth
                };
                RoomCanvas.Children.Add(line);
            }

            var combinedOutsideEdges = CombineOutsideEdges(outsideEdges);
            var outsideEdgeLinePoints = CalculateEdgeLinePoints(combinedOutsideEdges);

            var polyLineSegment = new PolyLineSegment(outsideEdgeLinePoints, true);
            var pathFigure = new PathFigure { StartPoint = outsideEdgeLinePoints.First() };
            pathFigure.Segments.Add(polyLineSegment);
            var pathGeometry = new PathGeometry();
            pathGeometry.Figures.Add(pathFigure);
            var path = new Path
            {
                Stroke = new SolidColorBrush(_outerCellLineColour),
                StrokeThickness = OuterCellLineWidth,
                StrokeEndLineCap = PenLineCap.Square,
                Data = pathGeometry
            };
            RoomCanvas.Children.Add(path);
        }
        private static IEnumerable<InternalRow> BuildInternalRowsForRoom(IReadOnlyList<Room> rooms, IImmutableList<InitialValue> initialValues, Room room)
        {
            var cellsWithInitialValues = initialValues.Select(initialValue => initialValue.Item1);
            var initialValuesInThisRoom = initialValues.Where(initialValue => room.Cells.Contains(initialValue.Item1)).Select(initialValue => initialValue.Item2);

            var cellsRemaining = room.Cells.Except(cellsWithInitialValues).ToImmutableList();
            var valuesRemaining = Enumerable.Range(1, room.Cells.Count).Except(initialValuesInThisRoom).ToImmutableList();

            return
                from cell in cellsRemaining
                from value in valuesRemaining
                select BuildInternalRow(rooms, cell, value, false);
        }
 private void AddRoom(Room room)
 {
     var roomControl = new RoomControl(room, _numRows, _sw, _sh) {Tag = TagType.Room};
     Canvas.SetLeft(roomControl, GridLineHalfThickness);
     Canvas.SetTop(roomControl, GridLineHalfThickness);
     BoardCanvas.Children.Add(roomControl);
 }