仿射变换如何在 Java 中真正发挥作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5670148/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does Affine Transform really work in Java?
提问by Simon Langhoff
I have been using Affine Transform to rotate a String in my java project, and I am not an experienced programmer yet, so it has taking me a long time to do a seemingly small task.. To rotate a string.
我一直在使用仿射变换在我的java项目中旋转一个字符串,我还不是一个有经验的程序员,所以我花了很长时间来完成一个看似很小的任务..旋转一个字符串。
Now I have finally gotten it to work more or less as I had hoped, except it is not as precisely done as I want... yet.
现在我终于让它或多或少地像我希望的那样工作,除了它没有像我想要的那样精确......
Since it took a lot of trial and error and reading the description of the affine transform I am still not quite sure what it really does. What I think I know at the moment, is that I take a string, and define the center of the string (or the point which I want to rotate around), but where does matrices come into this? (Apparently I do not know that hehe)
由于进行了大量的反复试验并阅读了仿射变换的描述,我仍然不太确定它的真正作用。我想我现在知道的是,我拿了一个字符串,并定义了字符串的中心(或我想要旋转的点),但是矩阵在哪里呢?(显然我不知道,呵呵)
Could anyone try and explain to me how affine transform works, in other words than the java doc? Maybe it can help me tweak my implementation and also, I just would really like to know :)
任何人都可以尝试向我解释仿射变换是如何工作的,换句话说,不是 Java 文档?也许它可以帮助我调整我的实现,而且,我真的很想知道:)
Thanks in advance.
提前致谢。
采纳答案by Micha? ?rajer
To understand what is affine transform and how it works see the wikipedia article.
要了解什么是仿射变换及其工作原理,请参阅维基百科文章。
In general, it is a linear transformation (like scaling or reflecting) which can be implemented as a multiplication by specific matrix, and then followed by translation (moving) which is done by adding a vector. So to calculate for each pixel [x,y] its new location you need to multiply it by specific matrix (do the linear transform) and then add then add a specific vector (do the translation).
通常,它是一种线性变换(如缩放或反射),可以实现为乘以特定矩阵,然后通过添加向量完成平移(移动)。因此,要计算每个像素 [x,y] 的新位置,您需要将其乘以特定矩阵(进行线性变换),然后添加然后添加特定向量(进行平移)。
回答by Carsten
In addition to the other answers, a higher level view:
除了其他答案,更高层次的观点:
Points on the screen have a x and a y coordinate, i.e. can be written as a vector (x,y). More complex geometric objects can be thought of being described by a collection of points.
Vectors (point) can be multiplied by a matrix and the result is another vector (point).
There are special (ie cleverly constructed) matrices that when multiplied with a vector have the effect that the resulting vector is equivalent to a rotation, scaling, skewing or with a bit of trickery translation of the input point.
屏幕上的点有 ax 和 ay 坐标,即可以写成向量 (x,y)。更复杂的几何对象可以被认为是由一组点来描述的。
向量(点)可以乘以矩阵,结果是另一个向量(点)。
有一些特殊的(即巧妙构造的)矩阵,当与向量相乘时,结果向量等效于旋转、缩放、倾斜或输入点的一些技巧平移。
That's all there is to it, basically. There are a few more fancy features of this approach:
基本上就是这样。这种方法还有一些更奇特的特性:
- If you multiply 2 matrices you get a matrix again (at least in this case; stop nit-picking ;-) ).
- If you multiply 2 matrices that are equivalent to 2 geometric transformations, the resulting matrix is equivalent to doing the 2 geometric transformations one after the other (the order matters btw).
- This means you can encode an arbitrary chain of these geometric transformations in a single matrix. And you can create this matrix by multiplying the individual matrices.
- Btw this also works in 3D.
- 如果你将 2 个矩阵相乘,你会再次得到一个矩阵(至少在这种情况下;停止挑剔;-))。
- 如果你乘以 2 个等价于 2 个几何变换的矩阵,得到的矩阵相当于一个接一个地进行 2 个几何变换(顺便说一句,顺序很重要)。
- 这意味着您可以在单个矩阵中对这些几何变换的任意链进行编码。您可以通过将各个矩阵相乘来创建此矩阵。
- 顺便说一句,这也适用于 3D。
For more details see the other answers.
有关更多详细信息,请参阅其他答案。
回答by belamoor
Here is purely mathematical video guide how to design a transformation matrix for your needs http://www.khanacademy.org/video/linear-transformation-examples--scaling-and-reflections?topic=linear-algebra
这是纯粹的数学视频指南,如何根据您的需要设计变换矩阵http://www.khanacademy.org/video/linear-transformation-examples--scaling-and-reflections?topic=linear-algebra
You will probably have to watch previous videos to understand how and why this matrices work though. Anyhow, it's a good resource to learn linear algebra if you have enough patience.
您可能需要观看以前的视频才能了解该矩阵的工作原理和原因。无论如何,如果您有足够的耐心,这是学习线性代数的好资源。
回答by trashgod
As a practical matter, I found two things helpful in understanding AffineTransform
:
实际上,我发现有两件事有助于理解AffineTransform
:
You can transform either a graphics context,
Graphics2D
, or any class that implements theShape
interface, as discussed here.Concatenated transformations have an apparent last-specified-first-appliedorder, also mentioned here.
您可以将任意一个图形上下文,
Graphics2D
或任何一类实现了Shape
接口,为讨论在这里。
回答by Howard
Apart from the answers already given by other I want to show a practical tip namely a pattern I usually apply when rotating strings or other objects:
除了其他人已经给出的答案之外,我想展示一个实用的技巧,即我在旋转字符串或其他对象时通常应用的模式:
- move the point of rotation (x,y) to the origin of space by applying
translate(-x,-y)
. - do the rotation
rotate(angle)
(possible also scaling will be done here) - move everything back to the original point by
translate(x,y)
.
- 通过应用将旋转点 (x,y) 移动到空间的原点
translate(-x,-y)
。 - 做旋转
rotate(angle)
(可能也将在这里进行缩放) - 将所有内容移回原点
translate(x,y)
。
Remember that you have to apply these steps in reverse order (see answer of trashgod).
请记住,您必须以相反的顺序应用这些步骤(请参阅垃圾神的回答)。
For strings with the first translation I normally move the center of the bounding box to the origin and with the last translate move the string to the actual point on screen where the center should appear. Then I can simply draw the string at whatever position I like.
对于第一次翻译的字符串,我通常将边界框的中心移动到原点,最后一次翻译将字符串移动到屏幕上应该出现中心的实际点。然后我可以简单地在我喜欢的任何位置绘制字符串。
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);
or alternatively
或者
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);