Java 将一个三角形变换为另一个三角形
嗨,我正在尝试创建仿射变换,它允许我将一个三角形变换为另一个三角形。我得到的是两个三角形的坐标。你能帮我吗 根据Adam Rosenfield的回答,我提出了以下代码,以防有人厌倦了自己求解方程:Java 将一个三角形变换为另一个三角形,java,math,affinetransform,Java,Math,Affinetransform,嗨,我正在尝试创建仿射变换,它允许我将一个三角形变换为另一个三角形。我得到的是两个三角形的坐标。你能帮我吗 根据Adam Rosenfield的回答,我提出了以下代码,以防有人厌倦了自己求解方程: public static AffineTransform createTransform(ThreePointSystem source, ThreePointSystem dest) { double x11 = source.point1.getX
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);
}
如果我理解正确,你的三角形有相同的大小和角度,所以你应该能够变换它们,使它们(至少)有一个共同点。在此之后,它们只能在旋转方面有所不同,或者可以镜像,因此您可以f.e.获取三角形线之间的角度,并尝试这些角度进行旋转,如果没有任何角度起作用,则可以镜像其中一个三角形 编辑:好的,这还不够,仿射变换还可以包含剪切和缩放。。。缩放可以很容易地完成,只需划分直线的长度,这也将为您提供一些有关三角形对应直线的信息,但剪切将更难
奥托,你就不能解一些方程组吗?毕竟,应该有一个变换矩阵和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
作为隐名并求解它,但是如果我没有遗漏什么(也许我遗漏了),您需要多加一点来完全指定转换,否则您将拥有额外的自由度(当然,您可以修复它).我假设你说的是2D。仿射变换矩阵中有9个值:
| a1 a2 a3 |
A = | a4 a5 a6 |
| a7 a8 a9 |
每一个都是向量,所以我们有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
求解这个6x6方程组可以得到仿射变换矩阵
A
。当且仅当源三角形的3个点不共线时,它将有一个唯一的解决方案。嘿,伙计们,在不失去一般性的情况下,使两个三角形的原点作为一个顶点(你可以稍后固定仿射移位),因此它们由点定义0,a,b,c,d然后将点x乘以矩阵NM
在哪里
M=反向(AB),因此您需要“移动”一个三角形,使坐标与第二个坐标匹配,而不改变三角形的外观?你有什么样的坐标?两个完全不同的三角形(形状和位置)。它们都位于同一个坐标系中。非常有用,谢谢!快速提醒一下,如果使用javascript html5 canvas,context.setTransform()函数将接收函数的精确输出,因此这是一个很好的工具,可以在每个坐标系中注册一个三角形点时,将图像从一个坐标系映射到另一个坐标系。我想将一个三角形镜像到一个完全不同的三角形(相同的坐标系)是不是6x6系统有点笨手笨脚?因为指定的问题“仿射变换”不意味着[a7,a8,a9]==[0,0,1]?我知道这就是你最终得到的结果,你似乎经历了一些不必要的扭曲才达到目的。k乘数的事情似乎也过于笼统。 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 | 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 |