Поворот 2D массива на 45 градусов - PullRequest
5 голосов
/ 19 июля 2010

Как я могу повернуть 2D прямоугольный массив целых чисел с нечетным числом строк на 45 градусов?

Так что-то вроде

int[] myArray = new int[,]   
{  
    {1, 0 ,1},  
    {0, 1 ,0},  
    {0, 0 ,0},  
} 

в

int[] rotatedArray = new int[,]   
{  
    {0, 1 ,0},  
    {0, 1 ,1},  
    {0, 0 ,0},  
}  

для любого размера (3x3, 5x5, 7x7 и т. д.).

5x5

0 0 0 0 0  
2 0 0 0 0  
1 1 1 1 1  
0 0 0 0 0  
0 0 0 0 0 

в

1 2 0 0 0  
0 1 0 0 0  
0 0 1 0 0  
0 0 0 1 0  
0 0 0 0 1 

5x5

0 0 0 3 0  
0 0 0 3 0  
0 0 0 3 0  
0 0 0 3 0  
0 0 0 3 0 

в

0 0 0 0 0  
0 0 0 0 3  
0 0 0 3 0  
0 0 3 3 0  
0 3 0 0 0  

Ответы [ 3 ]

1 голос
/ 19 июля 2010

Это код, написанный мной и моим другом, который решает это:

public static class ArrayExtensions
{
    public static Point RoundIndexToPoint(int index, int radius)
    {
        if (radius == 0)
            return new Point(0, 0);
        Point result = new Point(-radius, -radius);

        while (index < 0) index += radius * 8;
        index = index % (radius * 8);

        int edgeLen = radius * 2;

        if (index < edgeLen)
        {
            result.X += index;
        }
        else if ((index -= edgeLen) < edgeLen)
        {
            result.X = radius;
            result.Y += index;
        }
        else if ((index -= edgeLen) < edgeLen)
        {
            result.X = radius - index;
            result.Y = radius;
        }
        else if ((index -= edgeLen) < edgeLen)
        {
            result.Y = radius - index;
        }

        return result;
    }

    public static T[,] Rotate45<T>(this T[,] array)
    {
        int dim = Math.Max(array.GetLength(0), array.GetLength(0));

        T[,] result = new T[dim, dim];

        Point center = new Point((result.GetLength(0) - 1) / 2, (result.GetLength(1) - 1) / 2);
        Point center2 = new Point((array.GetLength(0) - 1) / 2, (array.GetLength(1) - 1) / 2);
        for (int r = 0; r <= (dim - 1) / 2; r++)
        {
            for (int i = 0; i <= r * 8; i++)
            {
                Point source = RoundIndexToPoint(i, r);
                Point target = RoundIndexToPoint(i + r, r);

                if (!(center2.X + source.X < 0 || center2.Y + source.Y < 0 || center2.X + source.X >= array.GetLength(0) || center2.Y + source.Y >= array.GetLength(1)))
                    result[center.X + target.X, center.Y + target.Y] = array[center2.X + source.X, center2.Y + source.Y];
            }
        }
        return result;
    }     
}
0 голосов
/ 19 июля 2010

Я думаю, что у нас есть следующие правила:

  1. Представьте матрицу как набор «рамок или коробок без центров» друг в друге, как «русские куклы».

  2. Элементы в центре стороны (сверху / слева / справа / снизу) движутся в направлении ближайшего угла по часовой стрелке.

  3. Уголки движутся в направлении следующего центра по часовой стрелке.

  4. Элементы, которые не являются ни углами, ни центрами, перемещаются к следующей точке (по часовой стрелке), которая находится на том же расстоянии от угла, что и в настоящее время.

Я начал писать код, но не думаю, что он тривиален, и у меня не было времени на тестирование.

0 голосов
/ 19 июля 2010

Вы можете попробовать эту библиотеку:

Math.NET Project для операций с матрицами ... http://numerics.mathdotnet.com/

Этот код также кажется полезным:

http://www.drunkenhyena.com/cgi-bin/view_net_article.pl?chapter=2;article=28#Rotation

Не забудьте про управляемые и неуправляемые пространства имен и классы DirectX. Лоты и много хороших вещей, чтобы проверить.

Например:

Матрица .. ::. Метод поворота (одиночный, MatrixOrder)

...