...я думаю над принудительным грубым методом, но его
эффективность может быть сомнительна, и не вздумайте пробовать его
без сопроцессора!
Сделайте наложение пиксель-на-пиксель из исходного изображение на
целевой (используя свойство Canvas.Pixels). Для каждого пикселя
осуществите преобразование полярных координат, добавьте
компенсирующий угол к полярной координате, затем спозиционируйте это
обратно на координаты прямоугольника, и разместите пиксель с новыми
координатами на целевом изображении. Также вы можете добавлять
какой-либо псевдослучайный пиксель через определенное их количество,
если хотите задать какую-то точность вашей операции.
Для преобразования X- и Y-координат объявлены следующие
переменные: X,Y = старые координаты пикселя
X1,Y1 = новые координаты пикселя
T = угол вращения (в радианах)
R, A - промежуточные величины, представляющие собой полярные координаты
R = Sqrt(Sqr(X) + Sqr(Y));
A = Arctan(Y/X);
X1 = R * Cos(A+T);
Y1 = R * Sin(A+T); Я отдаю себе отчет, что это не оптимальное
решение, поэтому, если вы найдете еще какое-либо решение, дайте мне
знать. В действительности мой метод работает, но делает это очень
медленно.
Создайте наложение пиксель-на-пиксель исходного
изображение на целевое (используя свойство Canvas.Pixels).
...это хорошее начало, но я думаю другой способ будет немного
лучшим. Создайте наложение пиксель-на-пиксель целевого изображения
на исходное так, чтобы нам было нужно вычислять откуда брать нужные
пиксели, а не думать над тем, куда их нужно поместить.
Для начала вот мой вариант формулы вращения: x, y = координаты в целевом изображении
t = угол
u, v = координаты в исходном изображении
x = u * cos(t) - v * sin(t)
y = v * cos(t) + u * sin(t) Теперь, если я захочу решить эти
уравнения и вычислить u и v (привести их к правой части уравнения),
то формулы будут выглядеть следующим образом (без гарантии, по этой
причине я и включил исходные уравнения!): x * cos(t) + y
u = --------------------
sqr(cos(t)) + sin(t)
v = y * cos(t) - x
--------------------
sqr(cos(t)) + sin(t)
Так, подразумевая, что вы уже знаете угол вращения, можно
вычислить константы cos(t) и 1/sqr(cos(t))+sin(t) непосредственно
перед самим циклом; это может выглядеть примерно так
(приблизительный код):
ct := cos(t);
ccst := 1/sqr(cos(t))+sin(t);
for x := 0 to width do
for y := 0 to height do
dest.pixels[x,y] := source.pixels[Round((x * ct + y) * ccst),
Round((y * ct - x) * ccst)];
|
Если вы хотите ускорить этот процесс, и при этом волнуетесь за
накопление ошибки округления, то вам следует обратить внимание на
используемую нами технологию: мы перемещаем за один раз один
пиксель, дистанция между пикселями равна u, v содержит константу,
определяющую колонку с перемещаемым пикселем. Я использую
расчитанные выше переменные как рычаг с коротким плечом (с
вычисленной длиной и точкой приложения). Просто поместите в (x,y) =
(1,0) и (x,y) = (0,1) и уравнение, приведенное выше:
duCol := ct * ccst;
dvCol := -ccst;
duRow := ccst;
dvRow := ct * ccst;
uStart := 0;
vStart := 0;
for x := 0 to width do
begin
u := uStart;
v := vStart;
for y := 0 to height do
begin
dest.pixels[x, y] := source.pixels[Round(u), Round(v)];
u := u + rowdu;
v := v + rowdv;
end;
uStart := uStart + duCol;
vStart := vStart + dvCol;
end;
|
Приведенный выше код можно использовать "как есть", и я не даю
никаких гарантий отностительно его использования!
Если вы в душе испытатель, и хотите попробовать вращение вокруг
произвольной точки, попробуйте поиграться со значенияим u и v: Xp, Yp (X-sub-p, Y-sub-p) точка оси вращения, другие константы определены выше
x = Xp + (u - Xp) * cos(t) - (y - Yp) * sin(t)
y = Yp + (y - Yp) * cos(t) - (x - Xp) * sin(t)
Оригинальные уравнения: x = u * cos(t) - v * sin(t)
y = v * cos(t) + u * sin(t) верны, но когда я решаю их для u
и v, я получаю это: x * cos(t) + y * sin(t)
u = -----------------------
sqr(cos(t)) + sqr(sin(t))
y * cos(t) - x * sin(t)
v = ------------------------
sqr(cos(t)) + sqr(sin(t)) |