Преобразуйте треугольник в другой треугольник
-
12-09-2019 - |
Вопрос
Привет, я пытаюсь создать аффинное преобразование, которое позволит мне преобразовать треугольник в другой.То, что у меня есть, - это координаты для 2 треугольников.Вы можете мне помочь?
Следуя ответу Адама Розенфилда, я придумал этот код на случай, если кому-то скучно решать уравнение самому :
public static AffineTransform createTransform(ThreePointSystem source,
ThreePointSystem dest) {
double x11 = source.point1.getX();
double x12 = source.point1.getY();
double x21 = source.point2.getX();
double x22 = source.point2.getY();
double x31 = source.point3.getX();
double x32 = source.point3.getY();
double y11 = dest.point1.getX();
double y12 = dest.point1.getY();
double y21 = dest.point2.getX();
double y22 = dest.point2.getY();
double y31 = dest.point3.getX();
double y32 = dest.point3.getY();
double a1 = ((y11-y21)*(x12-x32)-(y11-y31)*(x12-x22))/
((x11-x21)*(x12-x32)-(x11-x31)*(x12-x22));
double a2 = ((y11-y21)*(x11-x31)-(y11-y31)*(x11-x21))/
((x12-x22)*(x11-x31)-(x12-x32)*(x11-x21));
double a3 = y11-a1*x11-a2*x12;
double a4 = ((y12-y22)*(x12-x32)-(y12-y32)*(x12-x22))/
((x11-x21)*(x12-x32)-(x11-x31)*(x12-x22));
double a5 = ((y12-y22)*(x11-x31)-(y12-y32)*(x11-x21))/
((x12-x22)*(x11-x31)-(x12-x32)*(x11-x21));
double a6 = y12-a4*x11-a5*x12;
return new AffineTransform(a1, a4, a2, a5, a3, a6);
}
Решение
Я собираюсь предположить, что вы говорите здесь о 2D.Матрица аффинного преобразования содержит в себе 9 значений:
| a1 a2 a3 | A = | a4 a5 a6 | | a7 a8 a9 |
Есть 3 входные вершины x1
, x2
, и x3
, который при преобразовании должен стать y1
, y2
, y3
.Однако, поскольку мы работаем в однородных координатах, применяя A
Для x1
не обязательно дает y1
-- это дает кратное y1
.Итак, у нас также есть неизвестные множители k1
, k2
, и k3
, с уравнениями:
A*x1 = k1*y1 A*x2 = k2*y2 A*x3 = k3*y3
Каждое из них является вектором, так что на самом деле у нас есть 9 уравнений с 12 неизвестными, так что решение будет неполным.Если мы требуем, чтобы a7=0
, a8=0
, и a9=1
, тогда решение будет уникальным (этот выбор естественен, поскольку это означает, что если точка ввода является (x
, y
, 1), тогда выходная точка всегда будет иметь однородную координату 1, так что результирующее преобразование - это просто преобразование 2x2 плюс перевод).
Следовательно, это сводит уравнения к:
a1*x11 + a2*x12 + a3 = k1*y11 a4*x11 + a5*x12 + a6 = k1*y12 1 = k1 a1*x21 + a2*x22 + a3 = k2*y21 a4*x21 + a5*x22 + a6 = k2*y22 1 = k2 a1*x31 + a2*x32 + a3 = k3*y31 a4*x31 + a5*x32 + a6 = k3*y32 1 = k3
Итак, k1
= k2
= k3
= 1.Подключение их и преобразование в матричную форму дает:
| x11 x12 1 0 0 0 | | a1 | | y11 | | x21 x22 1 0 0 0 | | a2 | | y21 | | x31 x32 1 0 0 0 | * | a3 | = | y31 | | 0 0 0 x11 x12 1 | | a4 | | y12 | | 0 0 0 x21 x22 1 | | a5 | | y22 | | 0 0 0 x31 x32 1 | | a6 | | y32 |
Решая эту систему уравнений 6х6, вы получаете вашу матрицу аффинного преобразования A
.У него будет уникальное решение тогда и только тогда, когда 3 точки вашего исходного треугольника не являются коллинеарными.
Другие советы
Эй, ребята, без потери общности, сделайте так, чтобы два треугольника имели начало координат в виде одной вершины (позже вы можете применить аффинный сдвиг), чтобы они определялись точками 0, a, b, c, d затем умножьте свои баллы x по матрице NM
где
M = обратный(a b) <--- это матрица 2х2 с точками a и b как его столбцы
и
N = (c d)
Этого должно хватить.
Если я правильно понимаю, ваши треугольники имеют одинаковый размер и углы, поэтому вы должны быть в состоянии преобразовать их так, чтобы у них была (по крайней мере) одна общая точка.После этого они должны отличаться только поворотом или могут быть зеркально отражены, так что вы могли бы, например.найдите углы между линиями треугольника и попробуйте их повернуть, и они могут отражать один из треугольников, если ни один из углов не работает.
Редактировать:Хорошо, этого недостаточно, аффинные преобразования также могут содержать сдвиг и масштабирование...Масштабирование можно выполнить легко, просто разделите длину линий, это также даст вам некоторую информацию о соответствующих линиях треугольников, но срезать будет сложнее...
OTOH, не могли бы вы просто решить какую-нибудь систему уравнений для этого?В конце концов, должна быть матрица преобразования и 3 точки (новая и старая)...
Просто сформулируйте задачу в виде набора уравнений, а затем решите ее:
P1 * M = P1'
P2 * M = P2'
P3 * M = P3'
M
является ли матрица 3x3 подобной:
[m00, m01, m02;
m10, m11, m12;
0 , 0, 1]
И P_i
является кортежем [k*x_i, k*y_i, k]
(однородные координаты)...
Теперь вы можете попытаться расширить 3 матричных уравнения, показанных выше, и создать новую систему с m_ij
как распознать и решить это, но если я чего-то не упускаю (а возможно, так оно и есть), вам нужно на один пункт больше, чтобы полностью указать преобразование, иначе у вас будет дополнительная степень свободы (и, конечно, вы можете это исправить).