开发者

How does Affine Transform really work in Java?

开发者 https://www.devze.com 2023-02-24 16:44 出处:网络
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.

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.

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 :)

Thanks in advance.


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).


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.

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.

For more details see the other answers.


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:

  1. move the point of rotation (x,y) to the origin of space by applying translate(-x,-y).
  2. do the rotation rotate(angle) (possible also scaling will be done here)
  3. move everything back to the original point by 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);


As a practical matter, I found two things helpful in understanding AffineTransform:

  1. You can transform either a graphics context, Graphics2D, or any class that implements the Shape interface, as discussed here.

  2. Concatenated transformations have an apparent last-specified-first-applied order, also mentioned here.


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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消