Для меня это выглядит как линейное преобразование. Мы знаем это, потому что любая линия в исходном графе также является линией в преобразованном графе (это не всегда верно для демонстрации, которую вы дали, но будет верно, если вы будете следовать указаниям, которые вы дали в своем вопросе, и не допустите вогнутые вершины) , Я верю, что 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 - это ваша точка на оси x в форме (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)
(так что M => M 'и 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: Хорошо, я пробежал несколько ваших преобразований произвольных углов и понял, что сделал поспешные выводы, когда предположил, что ваше преобразование было линейным. Приведенные выше уравнения будут линейными только при двух условиях:
- Ваша новая сетка имеет форму некоторого повернутого параллелограмма (а у вас оригинальная квадратная, "нормальная" сетка)
- Положение вашей (0,0) исходной точки не меняется.
Теперь я не уверен, с какими степенями свободы вы позволяете позиционировать свои ручки, но, возможно, вы можете ограничить их так, чтобы ваше сеточное пространство всегда имело форму повернутого параллелограмма.