Пример #1
0
        private static Point[][] boolsToPaths(Virtual2DArray <bool> input)
        {
            int width  = input.Width;
            int height = input.Height;

            var results        = new List <Point[]>();
            var visitedUpArrow = Ut.NewArray <bool>(width, height);

            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    // every region must have at least one up arrow (left edge)
                    if (!visitedUpArrow[i][j] && input.Get(i, j) && !input.Get(i - 1, j))
                    {
                        results.Add(tracePolygon(input, i, j, visitedUpArrow));
                    }
                }
            }

            return(results.ToArray());
        }
Пример #2
0
        private static Point[] tracePolygon(Virtual2DArray <bool> input, int i, int j, bool[][] visitedUpArrow)
        {
            var result = new List <Point>();
            var dir    = Direction.Up;

            while (true)
            {
                // In each iteration of this loop, we move from the current edge to the next one.
                // We have to prioritise right-turns so that the diagonal-adjacent case is handled correctly.
                // Every time we take a 90° turn, we add the corner coordinate to the result list.
                // When we get back to the original edge, the polygon is complete.
                switch (dir)
                {
                case Direction.Up:
                    // If we’re back at the beginning, we’re done with this polygon
                    if (visitedUpArrow[i][j])
                    {
                        return(result.ToArray());
                    }

                    visitedUpArrow[i][j] = true;

                    if (!input.Get(i, j - 1))
                    {
                        result.Add(new Point(i, j));
                        dir = Direction.Right;
                    }
                    else if (input.Get(i - 1, j - 1))
                    {
                        result.Add(new Point(i, j));
                        dir = Direction.Left;
                        i--;
                    }
                    else
                    {
                        j--;
                    }
                    break;

                case Direction.Down:
                    j++;
                    if (!input.Get(i - 1, j))
                    {
                        result.Add(new Point(i, j));
                        dir = Direction.Left;
                        i--;
                    }
                    else if (input.Get(i, j))
                    {
                        result.Add(new Point(i, j));
                        dir = Direction.Right;
                    }
                    break;

                case Direction.Left:
                    if (!input.Get(i - 1, j - 1))
                    {
                        result.Add(new Point(i, j));
                        dir = Direction.Up;
                        j--;
                    }
                    else if (input.Get(i - 1, j))
                    {
                        result.Add(new Point(i, j));
                        dir = Direction.Down;
                    }
                    else
                    {
                        i--;
                    }
                    break;

                case Direction.Right:
                    i++;
                    if (!input.Get(i, j))
                    {
                        result.Add(new Point(i, j));
                        dir = Direction.Down;
                    }
                    else if (input.Get(i, j - 1))
                    {
                        result.Add(new Point(i, j));
                        dir = Direction.Up;
                        j--;
                    }
                    break;
                }
            }
        }
Пример #3
0
        public static GraphicsPath CloudPath(Virtual2DArray <bool> cloud, int cellSize, float margin)
        {
            var outlines = boolsToPaths(cloud);
            var diameter = new SizeF(cellSize / 2, cellSize / 2);
            var result   = new GraphicsPath();

            if (diameter.Width == 0 || diameter.Height == 0)
            {
                return(result);
            }
            for (int i = 0; i < outlines.Length; i++)
            {
                result.StartFigure();
                for (int j = 0; j < outlines[i].Length; j++)
                {
                    var point1 = outlines[i][j];
                    var point2 = outlines[i][(j + 1) % outlines[i].Length];
                    var point3 = outlines[i][(j + 2) % outlines[i].Length];
                    var rect   = new Rectangle(point2.X * cellSize, point2.Y * cellSize, cellSize, cellSize);

                    int dir1 = getDir(point1, point2);
                    int dir2 = getDir(point2, point3);

                    // Rounded corners ("outer" corners)
                    if (dir1 == 0 && dir2 == 2) // top left corner
                    {
                        result.AddArc(rect.X + margin, rect.Y + margin, diameter.Width, diameter.Height, 180, 90);
                    }
                    else if (dir1 == 2 && dir2 == 3)  // top right corner
                    {
                        result.AddArc(rect.X - margin - diameter.Width, rect.Y + margin, diameter.Width, diameter.Height, 270, 90);
                    }
                    else if (dir1 == 3 && dir2 == 1) // bottom right corner
                    {
                        result.AddArc(rect.X - margin - diameter.Width, rect.Y - margin - diameter.Height, diameter.Width, diameter.Height, 0, 90);
                    }
                    else if (dir1 == 1 && dir2 == 0) // bottom left corner
                    {
                        result.AddArc(rect.X + margin, rect.Y - margin - diameter.Height, diameter.Width, diameter.Height, 90, 90);
                    }

                    // Unrounded corners ("inner" corners)
                    else if (dir1 == 1 && dir2 == 3) // top left corner
                    {
                        result.AddLine(rect.X - margin, rect.Y - margin, rect.X - margin, rect.Y - margin);
                    }
                    else if (dir1 == 0 && dir2 == 1) // top right corner
                    {
                        result.AddLine(rect.X + margin, rect.Y - margin, rect.X + margin, rect.Y - margin);
                    }
                    else if (dir1 == 2 && dir2 == 0) // bottom right corner
                    {
                        result.AddLine(rect.X + margin, rect.Y + margin, rect.X + margin, rect.Y + margin);
                    }
                    else if (dir1 == 3 && dir2 == 2) // bottom left corner
                    {
                        result.AddLine(rect.X - margin, rect.Y + margin, rect.X - margin, rect.Y + margin);
                    }
                }
                result.CloseFigure();
            }
            return(result);
        }
Пример #4
0
        /// <summary>
        /// Given a <see cref="MoveFinder"/> or <see cref="PushFinder"/>, returns a <see cref="GraphicsPath"/> that can be
        /// used to visualise the area deemed "valid" by the relevant finder.
        /// </summary>
        /// <param name="finder">A <see cref="MoveFinder"/> or <see cref="PushFinder"/> object.</param>
        public GraphicsPath ValidPath(Virtual2DArray <bool> finder)
        {
            Point[][]    outlines = boolsToPaths(finder);
            SizeF        margin   = new SizeF(_cellWidth / 5, _cellHeight / 5);
            SizeF        diameter = new SizeF(_cellWidth / 2, _cellHeight / 2);
            GraphicsPath result   = new GraphicsPath();

            if (diameter.Width == 0 || diameter.Height == 0)
            {
                return(result);
            }
            for (int i = 0; i < outlines.Length; i++)
            {
                result.StartFigure();
                for (int j = 0; j < outlines[i].Length; j++)
                {
                    Point     point1 = outlines[i][j];
                    Point     point2 = outlines[i][(j + 1) % outlines[i].Length];
                    Point     point3 = outlines[i][(j + 2) % outlines[i].Length];
                    Rectangle rect   = CellRect(point2);

                    int dir1 = getDir(point1, point2);
                    int dir2 = getDir(point2, point3);

                    // Rounded corners ("outer" corners)
                    if (dir1 == 0 && dir2 == 2) // top left corner
                    {
                        result.AddArc(rect.X + margin.Width, rect.Y + margin.Height, diameter.Width, diameter.Height, 180, 90);
                    }
                    else if (dir1 == 2 && dir2 == 3)  // top right corner
                    {
                        result.AddArc(rect.X - margin.Width - diameter.Width, rect.Y + margin.Height, diameter.Width, diameter.Height, 270, 90);
                    }
                    else if (dir1 == 3 && dir2 == 1) // bottom right corner
                    {
                        result.AddArc(rect.X - margin.Width - diameter.Width, rect.Y - margin.Height - diameter.Height, diameter.Width, diameter.Height, 0, 90);
                    }
                    else if (dir1 == 1 && dir2 == 0) // bottom left corner
                    {
                        result.AddArc(rect.X + margin.Width, rect.Y - margin.Height - diameter.Height, diameter.Width, diameter.Height, 90, 90);
                    }

                    // Unrounded corners ("inner" corners)
                    else if (dir1 == 1 && dir2 == 3) // top left corner
                    {
                        result.AddLine(rect.X - margin.Width, rect.Y - margin.Height, rect.X - margin.Width, rect.Y - margin.Height);
                    }
                    else if (dir1 == 0 && dir2 == 1) // top right corner
                    {
                        result.AddLine(rect.X + margin.Width, rect.Y - margin.Height, rect.X + margin.Width, rect.Y - margin.Height);
                    }
                    else if (dir1 == 2 && dir2 == 0) // bottom right corner
                    {
                        result.AddLine(rect.X + margin.Width, rect.Y + margin.Height, rect.X + margin.Width, rect.Y + margin.Height);
                    }
                    else if (dir1 == 3 && dir2 == 2) // bottom left corner
                    {
                        result.AddLine(rect.X - margin.Width, rect.Y + margin.Height, rect.X - margin.Width, rect.Y + margin.Height);
                    }
                }
                result.CloseFigure();
            }
            return(result);
        }