Преобразовать треугольник в другой треугольник - PullRequest
14 голосов
/ 11 июля 2009

Привет, я пытаюсь создать аффинное преобразование, которое позволит мне преобразовать треугольник в другой. То, что у меня есть, это координаты для 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);
}

Ответы [ 4 ]

13 голосов
/ 11 июля 2009

Я предполагаю, что вы говорите о 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 |

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

2 голосов
/ 11 июля 2009

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

где

M = обратный ( a b ) <--- это матрица 2x2 с точками <strong>a и b в качестве столбцов

и

N = ( c d )

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

1 голос
/ 11 июля 2009

Просто сформулируйте задачу в виде системы уравнений, а затем решите ее:

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

1 голос
/ 11 июля 2009

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

РЕДАКТИРОВАТЬ: ОК, этого недостаточно, аффинные преобразования также могут содержать сдвиг и масштабирование ... Масштабирование может быть сделано легко, просто разделите длину линий, это также даст вам некоторую информацию о соответствующих линиях треугольников, но стрижка будет тяжелее ...

OTOH, не могли бы вы просто решить какую-то систему уравнений для этого? Ведь должна быть матрица преобразования и 3 точки (новая и старая) ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...