2010-05-31 2 views
4

У меня есть сетка в 2D-системе, подобная той, что изображена в переднем изображении, где даны все точки A, B, C, D, A ', B', C ', D' (это означает, что я знаю соответствующие x- и y-координаты).Координаты в искаженной сетке

Мне нужно вычислить x и y-координаты A (новый), B (новый), C (новый) и D (новый), когда сетка искажена (так что A 'перемещается в A' (новый), B 'перемещается в B' (новый), C 'перемещается в C' (новый), а D 'перемещается в D' (новый)).

Искажение происходит так, что линии сетки делятся на подстроки равной длины (что означает, например, что AB разделен на 5 частей равной длины | AB |/5 и A (новый) B (новый) делится на 5 частей равной длины | A (новый) B (новый) |/5).

Искажение выполняется с помощью класса DistortImage Sandy 3D Flash engine. (Моя практическая задача - исказить изображение, используя этот класс, где ручки не расположены в углах изображения like in this demo, но где-то внутри него).

alt text http://www.gefragt.de/distorted_grid.png

ответ

1

Пусть (u, v) представляют собой «текстурные» координаты. Ваши ручки остаются с одинаковыми координатами текстуры, независимо от искажений сетки.

Таким образом, в пространстве текстуры A = (0,0) B = (1,0) C = (1,1) D = (0,1) A '= (au, av) B' = (bu, bv) ...

Мы можем конвертировать из пространства текстуры в пространство пикселей.

Р (и, у) = А * (1-и) (1-v) + B и * (1-v) + С у V + D * (1-у) * v

(и, v координаты текстуры, и A, B, C, D см координаты пикселей)

Так что, если ваша ручка A»определяется, чтобы скоординировать текстуру (.35, .15), то положение A 'в пиксельном пространстве задается P (.35, .15).

Теперь скажите, что пользователь перетаскивает ручку A '.Нам нужно решить, для нового местоположения A. B, C, D остаются фиксированными. Это просто простая алгебра.

A' = A*(1-au)*(1-av) + B*au*(1-av) + C*au*av + D*(1-au)*av 
A' - B*au*(1-av) - C*au*av - D*(1-au)*av = A*(1-au)*(1-av) 
A = (A' - B*au*(1-av) - C*au*av - D*(1-au)*av)/((1-au)*(1-av)) 

Не так уж плохо. Тот же процесс получает формулы для других ручек. Вот мой код на C#. Она вызывается, когда любой из 8 «Thumbs» получить тащили:

 double au = .35, av = .15; // texture coordinates of A' 
    double bu = .8, bv = .2; // texture coordinates of B' 
    double cu = .8, cv = .6; // texture coordinates of C' 
    double du = .2, dv = .9; // texture coordinates of D' 

    // if we're dragging A' (AA), then move A, etc. 
    if (sender == ThumbAA) A = (AA - B*au*(1-av) - C*au*av - D*(1-au)*av)/((1-au)*(1-av)); 
    if (sender == ThumbBB) B = (BB - A*(1-bu)*(1-bv) - C*bu*bv - D*(1-bu)*bv)/(bu*(1-bv)); 
    if (sender == ThumbCC) C = (CC - A*(1-cu)*(1-cv) - B*cu*(1-cv) - D*(1-cu)*cv)/(cu*cv); 
    if (sender == ThumbDD) D = (DD - A*(1-du)*(1-dv) - B*du*(1-dv) - C*du*dv)/((1-du)*dv); 

    // update position of A', B', C', D' 
    AA = A*(1-au)*(1-av) + B*au*(1-av) + C*au*av + D*(1-au)*av; 
    BB = A*(1-bu)*(1-bv) + B*bu*(1-bv) + C*bu*bv + D*(1-bu)*bv; 
    CC = A*(1-cu)*(1-cv) + B*cu*(1-cv) + C*cu*cv + D*(1-cu)*cv; 
    DD = A*(1-du)*(1-dv) + B*du*(1-dv) + C*du*dv + D*(1-du)*dv; 

видео моего демо-приложения: http://screencast.com/t/NDU2ZWRj

Это не ответ на ваш точный вопрос о репозиционирование 4 ручки одновременно. Это то, что вы действительно хотите? Кроме того, дайте мне знать, если координаты текстур вашей руки не заданы. Вы можете конвертировать из пикселя в координаты текстуры, но это сложнее.

+0

Это может решить мою проблему. В ближайшее время я проверю его. Не могли бы вы разместить где-нибудь демо-приложение? – Carsten

+0

http://rapidshare.com/files/403571153/WarpGrid.exe.html (10 загрузок разрешено) –

+0

Это решает мою проблему. Большое спасибо! – Carsten

0

Вы уверены, что вы хотите получать во все это для ручек? в примерах ручки должны выступать в качестве опорных точек на мувиклипе для рисования, они никоим образом не связаны с изображением или искажением apon it. если вы хотите просто иметь обработчики внутри изображения, вам просто нужно будет компенсировать значение вычисления точки (например, topRightCorner = new Point(pointb.x +10, point.y - 10))

, если вы действительно хотите попасть в расчет точных точек, вы можете попробовать позвонить до localToGlobal(new Point(this.x, this.y)) от обработчика, чтобы определить, где он (и, следовательно, перевод, который был применен к нему). в противном случае вам придется иметь дело с трансформационными матрицами и точно определить, как класс вычисляет свои треугольники.

за очень хорошее руководство по матрицам, преобразования, смотрите здесь: senoular.com

удачи

+0

'localToGlobal' берет' Point' как params, а не две координаты. –

+0

исправлено. Спасибо – longstaff

+0

Спасибо за ответ. Я думаю, что ручки крепко связаны с изображением, поскольку они всегда находятся в одном и том же относительном положении: скажем, ABCD - это изображение, которое маскируется с помощью A'B'C'D '. Если вы интерпретируете A'newB'newC'newDnew как проекцию A'B'C'D '(= она просматривается с другой точки зрения и маскирует то же самое содержимое ABCD), я абсолютно уверен, что AnewBnewCnewDnew хорошо определен. Поскольку я имею дело с этой проблемой маскировки, простое перемещение ручек или localToGlobal не помогает. Afaik, матрицы преобразования не допускают требуемых искажений ... – Carsten

0

Вы хотите помочь с алгоритмической точки зрения (Transformations и т.д.) или вы ищете помощи о том, как достичь преобразования, специально использующие Sandy 3D flash engine?

+0

Это не ответ - вы действительно должны спрашивать об этом в разделе комментариев исходного вопроса. – brainjam

+0

есть. Но я не вижу ссылки для комментариев где-нибудь рядом с вопросом. – athena

+0

Мне нужно алгоритмическое решение. Речь идет не о Сэнди (я просто использую класс их искажения). – Carsten

0

Возможно, вы можете что-то выяснить, но я сомневаюсь, что вам или вашим пользователям понравится результат.

Чтобы узнать, почему, выберите точку в интерьере изображения. Скажите, что вы хотите немного переместить его вверх. Вы можете сделать это, переместив любой из четырех углов (попробуйте в демо). Это означает, что если вы хотите поместить туда ручку и переместить ее вверх, четыре угла будут двигаться в некоторой комбинации. Скорее всего, углы не будут делать то, что вы хотите. Например, все четыре из них могли двигаться на одну и ту же сумму, что привело к чистому переводу и отсутствию деформации. Или один угол мог двигаться, но, возможно, не тот, который вы ожидали. Существует бесконечность решений, и, скорее всего, вы выбираете не тот, который вы (или кто-то еще) ожидаете.

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

+0

Я думаю, что существует определенное решение: Скажем, ABCD - это изображение, которое замаскировано A'B'C'D '. Если вы интерпретируете A'newB'newC'newDnew как проекцию A'B'C'D '(= она просматривается с другой точки зрения и маскирует то же самое содержимое ABCD), я абсолютно уверен, что AnewBnewCnewDnew хорошо определен. – Carsten

+0

@ Карстен, искажение, которое вы используете, не является перспективным преобразованием - это билинейная интерполяция. Понятно, что если вы каким-то образом ограничите возможные семейства преобразований и как A, B, C, D должны реагировать на перемещение внутреннего поворота, вы можете сократить количество возможностей. – brainjam

+0

образ образца Карстен включен, безусловно, проецируется в перспективе. –

2

Это похоже на линейное преобразование для меня. Мы это знаем, потому что любая строка в исходном графе также является строкой в ​​преобразованном графе (это не всегда верно для демонстрации, которую вы дали, но будет верно, если вы будете следовать указаниям, которые вы указали в своем вопросе, и не допускать вогнутых вершин) , Я верю, что AS3 имеет встроенную поддержку матричных манипуляций преобразования. Если нет, вы можете реализовать их самостоятельно.

[ x' ] = [ a b ] x [ x ] 
[ y' ]  [ c d ] [ y ] 

Это матрицы. Первый - это вектор (ваша конечная точка) и равен некоторой матрице 2x2, умноженной на вектор (ваша исходная точка)

Если вы не знакомы с умножением матрицы, это может быть упрощено:

x' = a*x + b*y 
y' = c*x + b*y 

Любое линейное преобразование может быть представлено такой матрицей a-b, c, и d. Выберите номера для каждого из них, и вы получите линейное преобразование. Итак, как вы находите значения a, b, c и d, которые дадут вам ваши?

Для четырех неизвестных вам нужны четыре уравнения. Если вы посмотрите на приведенные выше уравнения, вы увидите, что одна точка («вектор») и ее преобразование дадут вам два уравнения. Итак ... нам нужны два момента. Как вы увидите позже, будет полезно выбрать точки в невращаемой форме (m, 0) и (0, n) (т. Е. Один вдоль вашей оси x, а другой вдоль вашей оси y).

В вашем примере их легко найти! Это B и D (если A или C - ваше происхождение)!

Я буду использовать немного другое обозначение: «простые» для преобразованных версий точек.

B => B' 
B_x => B'_x 
B_y => B'_y 

Если вы знаете, что раньше, и после того, как координаты B и D, вы можете найти преобразование матрицы A, B, C, D.

Настройка ваших уравнений:

B'_x = a * B_x + b * B_y 
B'_y = c * B_x + d * B_y 

D'_x = a * D_x + b * D_y 
D'_y = c * D_x + d * D_y 

Теперь, давайте скажем, что B ваша точка оси х, в форме (B_x, 0). Скажем, D - ваша точка оси y, в форме (0, D_y). Если это наоборот, переключите их. Здесь мы предполагаем, что ваше происхождение A = (0,0), как и в большинстве приложений Flash.

Настройка B_y = 0 и D_X = 0, получим:

B'_x = a * B_x + b * 0 
B'_y = c * B_x + d * 0 
D'_x = a * 0 + b * D_y 
D'_y = c * 0 + d * D_y 

Используя полномочия алгебры, мы находим:

a = B'_x/B_x 
c = B'_y/B_x 
b = D'_x/D_y 
d = D'_y/D_y 

Так, короче говоря:

Если вы знать исходные точки: (вершины на исходной оси x и y)

M = (M_x, 0) 
N = (0 , N_x) 

и их трансформированные/искаженные точки

M' = (M'_x, M'_y) 
N' = (N'_x, N'_y) 

(так что М => М 'и N => N')

затем вычислить и сохранить эти четыре переменные:

a = M'_x/M_x 
b = N'_x/N_y 
c = M'_y/M_x 
d = N'_y/N_y 

и наконец:

(x, y) => (a*x + b*y , c*x + d*y) 

edit: Хорошо, я пробежал несколько из вашего преобразования с произвольным углом и понял, что я подпрыгнул до выводов, когда я предположил, что ваша трансформация была линейной. Уравнения выше будут линейными только при двух условиях:

  1. Вашей новая сетка формы некоторых повернута parallelogram (и вы оригинал квадрат, «нормальная» сетка)
  2. Положения ваших (0, 0) исходная точка не меняется.

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

+1

Это не линейное преобразование. Сетка «видимо» искажена с преобразованием перспективы, которое является нелинейным. –

+0

@ Eamon - См. Edit :(Вот почему я хотел бы получить ответ на этот вопрос, который лучше моего. –

+0

Я думаю, что любые нелинейные аспекты могут быть решены путем переключения на матричное уравнение более высокого порядка. не уверен, какую форму следует использовать, но работа IIRC 3D часто (например,в openGL), выполненный с помощью какой-либо матрицы 4x4. OTOH, учитывая, что у вас есть только 3 контрольные точки (и, таким образом, может поместиться любая проблема с 4-мя операциями, масштабированием X и Y, вращением и перекосом, все возможно с 2x2), я думаю, что вам это не понадобится – BCS

3

Я не могу дать вам полный ответ, но я уверен, что вы найдете его в «Основах картирования текстур и деформации изображения» Павла С. Хекберта: http://www.cs.cmu.edu/~ph/texfund/texfund.pdf (в приложении содержится исходный код для всех виды сопоставлений)

+0

Спасибо за ссылку! –

+0

Отличный ресурс! –

+0

Спасибо за ссылку. Это отличное и очень полезное чтение. – Carsten

0

Вы говорите о двумерной системе, но искажение, которое вы применяете, - это трехмерное искажение (хотя и проецируемое обратно вниз на 2d, конечно) - это намеренно?

В общем, я на самом деле не уверен, что возможно вычислить новое местоположение A'new без дополнительной информации о перспективной проекции, чем просто новые местоположения ABCD. В конце концов, перспективная проекция преувеличивает соседние расстояния и сжимает отдаленные - и степень, в которой это происходит, зависит от расстояния от фокальной точки (что эквивалентно FOV).

В любом случае было бы проще всего использовать все необходимое для вычисления проекции - если вы можете получить исходную матрицу преобразования и перспективное преобразование, вы можете прямо применить их к A 'B 'и D'.

Смежные вопросы