Преобразование треугольника в другой треугольник

Привет я пытаюсь создать аффинное преобразование, которое позволит мне превратить треугольник в другой. У меня есть координаты двух треугольников. Вы можете мне помочь?

после ответа Адама Розенфилда я придумал этот код на случай, если кому-то скучно решать уравнение самому :

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);
}

4 ответов


я собираюсь предположить, что вы говорите о 2D здесь. Аффинная матрица преобразования имеет 9 значений:

    | a1 a2 a3 |
A = | a4 a5 a6 |
    | a7 a8 a9 |

есть 3 входных вершин x1, x2 и x3, который при преобразовании должен стать y1, y2, y3. Однако, поскольку мы работаем в однородных координатах, применяя A to 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 плюс a перевод.)

следовательно, это сводит уравнения к:

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 |

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


Эй, ребята, без потери общности, сделайте два треугольника имеют начало координат как одну вершину (вы можете привязать аффинный сдвиг позже), поэтому они определяются точками 0, a, b, c, d затем умножьте свои очки x по матрице NM

здесь

M = обратный(a b) a и b в качестве столбцов

и

N = (c d)

Это должно сделать это.


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

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

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 как инкогнито и решить его, но если я чего-то не хватает (и, возможно, я), вам нужно еще один пункт, чтобы полностью указать преобразование, или в противном случае у вас будет дополнительная степень свободы (и, конечно, вы можете это исправить).