width と height のあるデータを一次元で扱っているとき、それを回転することを考える。
なお、並べ替え先に外部領域を使う。
また、記事名は配列としているが、記事内のコードはSpan
として扱っている。
参考イメージ画像。
右回転
行と列が入れ替わる。
並びは、Y軸は逆順・X軸は正順
public static void Rotate2dRight<T>(scoped ReadOnlySpan<T> source, int width, int height, scoped Span<T> destination) { int i = 0; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var row = (height - y - 1) * width; destination[i++] = source[row + x]; } } }
左回転
行と列が入れ替わる。
並びは、Y軸は正順・X軸は逆順
public static void Rotate2dLeft<T>(scoped ReadOnlySpan<T> source, int width, int height, scoped Span<T> destination) { int i = 0; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { var row = y * width; destination[i++] = source[row + (width - x - 1)]; } } }
180°回転
全体を逆順にするだけ。
public static void Rotate2d180<T>(scoped ReadOnlySpan<T> source, scoped Span<T> destination) { source.CopyTo(destination); destination[..source.Length].Reverse(); }
左右(X軸)反転
ついでに反転も。
回転と異なり、行と列が入れ替わらない。
X軸を逆順にするだけ。
public static void Invert2dX<T>(scoped ReadOnlySpan<T> source, int width, int height, scoped Span<T> destination) { for (int y = 0; y < height; y++) { var row = y * width; source.Slice(row, width).CopyTo(destination); destination[..width].Reverse(); destination = destination[width..]; } }
上下(Y軸)反転
Y軸を逆順にするだけ。
public static void Invert2dY<T>(scoped ReadOnlySpan<T> source, int width, int height, scoped Span<T> destination) { for (int y = 0; y < height; y++) { var row = (height - y - 1) * width; source.Slice(row, width).CopyTo(destination); destination = destination[width..]; } }