将三角形转换为另一个三角形

时间:2009-07-11 17:44:04

标签: java math affinetransform

您好我正在尝试创建仿射变换,这将允许我将三角形转换为另一个三角形。我所拥有的是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 个答案:

答案 0 :(得分:13)

我假设你在这里谈论2D。仿射变换矩阵中有9个值:

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

有3个输入顶点x1x2x3,它们在转换后应变为y1y2y3。但是,由于我们在齐次坐标系中工作,因此将A应用于x1并不一定会给y1 - 它会给出y1的倍数。因此,我们还有未知的乘数k1k2k3,其中包含以下公式:

A*x1 = k1*y1
A*x2 = k2*y2
A*x3 = k3*y3

每个都是一个向量,所以我们确实有12个未知数的9个方程,因此解决方案将受到不足。如果我们需要a7=0a8=0a9=1,则解决方案将是唯一的(此选择很自然,因为这意味着输入点是否为{xy,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个点不共线时,它将具有唯一的解决方案。

答案 1 :(得分:2)

嘿,伙计们,没有失去一般性,让两个三角形的原点作为一个顶点(你可以稍后在仿射变换上),所以它们由点 0,a,b定义, c,d 然后将您的点 x 乘以矩阵NM

,其中

M =逆( ab )< ---这是2x2矩阵,其中 a b 为其列

N =( c d

应该这样做。

答案 2 :(得分:1)

如果我理解正确,你的三角形具有相同的大小和角度,所以你应该能够转换它们,使它们(至少)有一个共同点。在此之后,它们应该只有不同的旋转或镜像,所以你可以f.e.获取三角形线之间的角度并尝试这些角度进行旋转,如果没有角度可以工作,则可以镜像其中一个三角形。

编辑:好的,这还不够,仿射变换也可以包含剪切和缩放......缩放可以很容易地完成,只需要划分行的长度,这也会给你一些关于三角形相应行的信息,但剪毛会更难......

OTOH,你难道不能为此解决一些方程式系统吗?毕竟,应该有一个转换矩阵和3个点(新旧)......

答案 3 :(得分:1)

将问题形成一组方程式,然后解决它:

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个matricial方程并创建一个新的系统,m_ij作为不可知并解决它,但是如果我没有遗漏某些东西(也许我是),你需要更多一点来完全指定转换,否则你将获得额外的自由度(当然你可以修复它)。