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