仿射变换在Java中是如何工作的?

仿射变换在Java中是如何工作的?,java,matrix,rotation,drawstring,affinetransform,Java,Matrix,Rotation,Drawstring,Affinetransform,在我的java项目中,我一直在使用仿射变换来旋转字符串,而且我还不是一个有经验的程序员,所以我花了很长时间来完成一项看似很小的任务。。旋转一根绳子 现在我终于让它或多或少像我所希望的那样工作了,只是它没有像我希望的那样精确地完成。。。然而 由于它需要大量的尝试和错误,并阅读了仿射变换的描述,我仍然不太确定它到底做了什么。我想我现在知道的是,我取一个字符串,定义字符串的中心(或者我想旋转的点),但是矩阵是从哪里来的呢?(显然我不知道呵呵) 除了java文档,还有谁能试着向我解释仿射变换是如何工作的

在我的java项目中,我一直在使用仿射变换来旋转字符串,而且我还不是一个有经验的程序员,所以我花了很长时间来完成一项看似很小的任务。。旋转一根绳子

现在我终于让它或多或少像我所希望的那样工作了,只是它没有像我希望的那样精确地完成。。。然而

由于它需要大量的尝试和错误,并阅读了仿射变换的描述,我仍然不太确定它到底做了什么。我想我现在知道的是,我取一个字符串,定义字符串的中心(或者我想旋转的点),但是矩阵是从哪里来的呢?(显然我不知道呵呵)

除了java文档,还有谁能试着向我解释仿射变换是如何工作的吗?也许它可以帮助我调整我的实现,而且,我真的很想知道:)


提前感谢。

要了解什么是仿射变换及其工作原理,请参阅维基百科


一般来说,它是一种线性变换(如缩放或反射),可以通过特定矩阵的乘法实现,然后通过添加向量进行平移(移动)。因此,要计算每个像素[x,y]的新位置,需要将其乘以特定矩阵(进行线性变换),然后再加上特定向量(进行平移)。

作为一个实际问题,我发现有两件事有助于理解:

  • 如前所述,您可以转换图形上下文或实现该接口的任何类

  • 级联转换具有明显的最后指定的第一个应用顺序,也提到了


  • 除了其他人已经给出的答案外,我想展示一个实用技巧,即旋转弦或其他物体时通常采用的模式:

  • 通过应用
    平移(-x,-y)
    将旋转点(x,y)移动到空间原点
  • 进行旋转
    旋转(角度)
    (此处也可能进行缩放)
  • 通过
    translate(x,y)
    将所有内容移回原点
  • 记住,你必须按相反的顺序应用这些步骤(参见垃圾神的答案)

    对于第一次平移的字符串,我通常将边界框的中心移动到原点,最后一次平移时,将字符串移动到屏幕上中心应该出现的实际点。然后我可以在我喜欢的任何位置画线

    Rectangle2D r = g.getFontMetrics().getStringBounds(text, g);
    g.translate(final_x, final_y);
    g.rotate(-angle);
    g.translate(-r.getCenterX(), -r.getCenterY());
    g.drawString(text, 0, 0);
    
    或者

    Rectangle2D r = g.getFontMetrics().getStringBounds(text, g);
    AffineTransform trans = AffineTransform.getTranslateInstance(final_x, final_y);
    trans.concatenate(AffineTransform.getRotateInstance(-angle));
    trans.concatenate(AffineTransform.getTranslateInstance(-r.getCenterX(), -r.getCenterY()));
    g.setTransform(trans);
    g.drawString(text, 0, 0);
    

    除其他答案外,更高层次的观点:

    • 屏幕上的点具有x和y坐标,即可以写成矢量(x,y)。更复杂的几何对象可以认为是由一组点来描述的

    • 向量(点)可以与矩阵相乘,结果是另一个向量(点)

    • 有一些特殊的(即巧妙构造的)矩阵,当与向量相乘时,产生的向量相当于输入点的旋转、缩放、倾斜或一点巧妙的平移

    基本上就是这样。这种方法还有一些更奇特的特性:

    • 如果将两个矩阵相乘,则会再次得到一个矩阵(至少在本例中,停止挑剔;-)
    • 如果将两个等价于两个几何变换的矩阵相乘,则生成的矩阵等价于一个接一个地进行两个几何变换(顺便说一句,顺序很重要)
    • 这意味着您可以在单个矩阵中对这些几何变换的任意链进行编码。你可以通过乘以各个矩阵来创建这个矩阵
    • 顺便说一句,这也适用于3D

    有关更多详细信息,请参见其他答案。

    这里是一个纯数学视频指南,介绍如何根据您的需要设计变换矩阵


    不过,您可能需要观看之前的视频,以了解矩阵的工作方式和原因。无论如何,如果你有足够的耐心,这是学习线性代数的一个很好的资源。

    这更多的是一个数学问题,而不是编程。查看Wikipedia的页面:并不是说它比JavaDoc更容易理解不幸的是,这只是你必须通过暴力强迫你学习的事情之一,伊姆霍。