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

StackOverflow https://stackoverflow.com/questions/1114257

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top