Как повернуть двумерный массив в произвольную степень? - PullRequest
0 голосов
/ 02 июня 2011

Скажем, у меня есть bool [] [], и я хочу повернуть его на 37 градусов.Я знаю, что трансформация не всегда будет идеальной, и это нормально.Здесь я подготовил множество ответов, похожих на мой вопрос, но единственные решения, которые я нашел, решают проблему только с шагом 90 градусов.

Ответы [ 4 ]

6 голосов
/ 02 июня 2011

Лучший способ - это циклически перемещаться по местам назначения и для каждого из них читать правильное местоположение источника. Если вы попробуете наоборот (то есть зацикливание на источнике и запись на месте назначения), вы получите пробелы.

Формула вращения проста ...

source_x = dest_x * c + dest_y * s + x0
source_y = dest_x * -s + dest_y * c + y0

, где c - косинус угла, s - синус угла, а x0, y0 используются для правильного перевода повернутого изображения. В псевдокоде

for y = 0, 1, ... dest_height
    for x = 0, 1, ... dest_width
        src_x = c*x + s*y + x0
        src_y = -s*x + c*y + y0
        copy from source[src_y][src_x] to dest[y][x]

x0, y0 можно вычислить так, чтобы центр источника оказался в центре назначения на

 x0 = src_width/2 - c*dest_width/2 - s*dest_height/2
 y0 = src_height/2 - c*dest_height/2 + s*dest_width/2

Если вместо использования c = cos(angle) и s = sin(angle) вы масштабируете их с коэффициентом k, результирующее изображение будет повернуто и увеличено вокруг центра.

Обратите внимание, что формулы являются билинейными в x и y; это означает, что вы можете использовать полную формулу для полного значения для первого пикселя строки, а затем просто сделать src_x += c и src_y -= s для каждого элемента той же строки, потому что именно это происходит при переходе от x к x+1.

Также обратите внимание, что в зависимости от размера источника и назначения может оказаться, что вычисленный элемент источника недоступен из-за отсутствия изображения. В этом случае есть несколько обычно используемых опций

  1. Введите фиксированное значение (например, false)
  2. Не записывайте эту ячейку назначения
  3. Выполните «зажим», ограничивая обе координаты максимально допустимым значением перед считыванием
  4. Выполните «мозаику», нормализуя координаты с помощью оператора по модулю
4 голосов
/ 02 июня 2011

Где x, y - ваши декартовы координаты, а R - угол поворота:

newx = x * cos(R) - y * sin(R)
newy = x * sin(R) + y * cos(R)
1 голос
/ 02 июня 2011

Предполагая, что вы вращаете растровое изображение, я бы сначала посмотрел на использование инфраструктуры обработки изображений (например, System.Drawing) для достижения того, чего вы хотите. Скажем, возьмите bool, превратите его в растровое изображение размером 1 бит в секунду, нарисуйте его повернутым и прочитайте обратно.

Если это не то, что вам нужно, вы можете либо использовать вращение, предоставляемое wberry, и применить его к каждому bool, либо, если производительность повышена, написать свой собственный растеризованный прямоугольный растеризатор. Чтобы сделать последнее, посмотрите на некоторые старые учебники по графическому программированию о том, как текстурировать карту произвольных 2D полигонов.

0 голосов
/ 02 июня 2011

Если вы действительно, действительно не хотите делать это самостоятельно, рассмотрите возможность использования чего-то вроде AForge - более конкретно AForge.Imaging.Filters.RotateBicubic . Эта процедура обрабатывает изображения 24bpp и 8bpp, поэтому вам нужно повернуть содержимое RGB (как изображение 24bpp) отдельно от альфа-канала (как изображение 8bpp).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...