首页 > 解决方案 > 旋转 3d 阵列

问题描述

我有一个由 a 表示的 3D 数组int[,,]。我希望能够在任何 3 个轴上将其旋转 90(或-90)度增量。

例子

对于以下二维数组:

1 2 3
4 5 6

我希望这个结果:

4 1
5 2
6 3

我想要同样的逻辑,但适用于 3D 数组。

标签: c#arraysdata-structures

解决方案


这是你如何做到的。

您不需要乘以矩阵,因为您只是在移动值而不更改它们。您所要做的就是将每个输入单元映射到其输出单元。

从 2D 开始

想象一下,您有一个 3x4x1 的 3D 数组。这可以用一个 3x4 的二维数组来表示。

这是旋转时每个单元格的关联方式:

// Rotating 90 degrees clockwise
output[i, j] = input[j, maxHeight - i];

// Rotating 90 degrees counter clockwise
output[i, j] = input[maxWidth - j, i];

(您可以在本文末尾找到在上下文中使用这些行的完整代码。)

添加第三维

现在不是 3x4x1,而是想象我们有一个 3x4x2。这相当于旋转两个二维数组。这是旋转代码的样子。

// Rotating 90 degrees clockwise (around z axis)
output[i, j, k] = input[j, maxHeight - i, k];

// Rotating 90 degrees counter clockwise (around z axis)
output[i, j, k] = input[maxWidth - j, i, k];

从那里,您可以重复相同的模式以围绕另一个轴旋转。

// Rotating around the x axis (i doesn't change)
output[i, j, k] = input[i, maxHeight - k, j           ];
output[i, j, k] = input[i, k            , maxDepth - j];

// Rotating around the y axis (j doesn't change)
output[i, j, k] = input[maxWidth - k, j, i           ];
output[i, j, k] = input[k           , j, maxDepth - i];

完整代码

以下代码执行以下操作:

  1. 它创建一个 4x3 2D 数组并打印它。
  2. 它通过将原始数组顺时针旋转 90 度来创建一个新数组并打印它。
  3. 它通过将原始数组逆时针旋转 90 度来创建一个新数组并打印它。

该代码还包含一个名为的方法,该方法Rotate90DegreesClockwiseAroundZAxis说明了如何围绕 Z 轴旋转 3D 数组。您可以使用此代码生成围绕另一个轴旋转的方法。

static void Main(string[] args)
{
    int[,] grid = new int[4, 3];

    int counter = 0;
    for (int j = 0; j < grid.GetLength(1); j++)
    {
        for (int i = 0; i < grid.GetLength(0); i++)
        {
            grid[i, j] = counter++;
        }
    }

    Debug.WriteLine("Default:");
    PrintGrid(grid);

    var rotated90Grid = Rotate90DegreesClockwise(grid);
    Debug.WriteLine("Rotated 90:");
    PrintGrid(rotated90Grid);

    var rotated270Grid = Rotate90DegreesCounterClockwise(grid);
    Debug.WriteLine("Rotated 270:");
    PrintGrid(rotated270Grid);
}

static int[,] Rotate90DegreesClockwise(int[,] input)
{
    var inputWidth = input.GetLength(0);
    var inputHeight = input.GetLength(1);

    // We swap the sizes because rotating a 3x4 yields a 4x3.
    var output = new int[inputHeight, inputWidth];

    var maxHeight = inputHeight - 1;

    for (int j = 0; j < output.GetLength(1); j++)
    {
        for (int i = 0; i < output.GetLength(0); i++)
        {
            output[i, j] = input[j, maxHeight - i];
        }
    }

    return output;
}

static int[,] Rotate90DegreesCounterClockwise(int[,] input)
{
    var inputWidth = input.GetLength(0);
    var inputHeight = input.GetLength(1);

    // We swap the sizes because rotating a 3x4 yields a 4x3.
    var output = new int[inputHeight, inputWidth];

    var maxWidth = inputWidth - 1;

    for (int j = 0; j < output.GetLength(1); j++)
    {
        for (int i = 0; i < output.GetLength(0); i++)
        {
            output[i, j] = input[maxWidth - j, i];
        }
    }

    return output;
}

static int[,,] Rotate90DegreesClockwiseAroundZAxis(int[,,] input)
{
    var inputWidth = input.GetLength(0);
    var inputHeight = input.GetLength(1);
    var inputDepth = input.GetLength(1);

    // We swap the sizes because rotating a 3x4x5 yields a 4x3x5.
    var output = new int[inputHeight, inputWidth, inputDepth];

    var maxHeight = inputHeight - 1;

    for (int k = 0; k < inputDepth; k++)
    {
        for (int j = 0; j < output.GetLength(1); j++)
        {
            for (int i = 0; i < output.GetLength(0); i++)
            {
                output[i, j, k] = input[j, maxHeight - i, k];
            }
        }
    }

    return output;
}

static void PrintGrid(int[,] grid)
{
    for (int j = 0; j < grid.GetLength(1); j++)
    {
        for (int i = 0; i < grid.GetLength(0); i++)
        {
            Debug.Write($"{grid[i, j]:D2} ");
        }

        Debug.WriteLine("");
    }
    Debug.WriteLine("---------------");
}

输出

Default:
00 01 02 03 
04 05 06 07 
08 09 10 11 
---------------
Rotated 90:
08 04 00 
09 05 01 
10 06 02 
11 07 03 
---------------
Rotated 270:
03 07 11 
02 06 10 
01 05 09 
00 04 08 
---------------

推荐阅读