Graphics2D rotate methods. What's the difference? - java

The Java API doesn't really explain this very well and I'm still unsure.
What is the difference between these two Graphics2d overloaded method calls?
public abstract void rotate(double theta)
and
public abstract void rotate(double theta,
double x,
double y)
The Java Doc is here:
http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html#translate%28int,%20int%29
What I got from the documentation, was that the second rotate method translates the graphics object, rotates it, and translates it back. My confusion is about where drawing graphics fits in if it is already translated back to the previous origin.
If the graphics is rotated, can I go off the previous coordinate system (with the origin at (0,0)) and have everything end up where I'd expect?
My goal is to rotate the graphics around the center of a image (thus the translation), and then rotate and redraw the image. After that, I'd like to reset the graphics back to normal (or simply discard that version of graphics?).
Thanks in advance for any help.

If I remember right, Graphics2D#rotate(double) rotates around the top/left corner of the Graphics context (based on it's current transformation), where as Graphics2D#rotate(double, double, double) allows you to define the anchor point around which the Graphics context will be rotated. Sometimes, you just have to give it a try

Related

Swing issue: drawing rectangles over the pdf image and keep their size and positions consistent when zooming in and out

I have a rather pressing question in regards to Swing, which I haven't touched for many years.
I have a code that allows the user to draw different rectangles on the pdf document (contained within JPanel). I draw them, move them, resize them, select them, and even write text on them. What I can't do is to keep them consistent when I zoom the document. As the document gets bigger, the rectangles I've drawn stay at the same position and the same size.
I was wondering if there's a relatively easy logic to track the zooming level and, most importantly, update the rectangles accordingly. I can retrieve zoom factor, it's a float, but, unfortunately, I'm using Rectangle object, which uses int for x, y, height, and width. It will be a hassle to convert it to Rectangle.Float, and I wanted to save it for a last resort.
I've tried to use AffineTransform, but I'm not quite familiar with it, for some reason I'm getting the wrong coordinates for y. Can anyone explain to me:
What's the best way to control the Rectangle object, as the pdf document gets zoomed in and out?
If AffineTransform is the best way, how should I handle it (maybe there's a link to a good explanation, if so - I couldn't find it)?
This is the only issue I've been struggling with and it's getting a bit frustrating now.
To scale using an AffineTransform:
Get the transform T of the Graphics object G
Create an AffineTransform object A
Set the scale of A
Set the transform of the G to A
Draw the shapes
Set the transform of G back to T
Translated into code - assuming scale is the value to scale by:
#Override
protected void paintComponent(Graphics gr){
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
AffineTransform prevTransform = g.getTransform();
AffineTransform at = new AffineTransform(prevTransform);
at.scale(scale, scale);
g.setTransform(at);
g.drawRect(...);
g.setTransform(prevTransform);
}

Rotating Image (getting it back to original position)

Using "Affine Transformation" I can rotate imageA easily. As well, imageA will move along with imageB. However, I cannot seem to find a way to move imageA back to its original position after I have rotated it.
(I have done some research on some sites and apparently the best method is to move the image back to its original position so that it looks like its rotating from an anchor point.)
Heres my code so far:
public void paintComponent(Graphics g) {
super.paintComponent(g);
AffineTransform af = new AffineTransform();
Graphics2D g2d = (Graphics2D) g;
af.translate(imageBx, imageBy); // moves ImageA to imageb's position
af.rotate(Math.toRadians(angle), imageB.getHeight(this) / 2, imageB.getWidth(this) / 2);
g2d.drawImage(imageA, af, null);
g2d.drawImage(imageB, imageBx, imageBy, null);
}
If anyone can help me move imageA back to its original position (which is right on imageB) that would extremely helpful!
I looked that over, but the code rotates the entire panel; I just want to rotate one Image on a fixed rotate point.
Two things may help guide your understanding:
The example cited uses rotate(double theta); it is preceeded by a translation to the origin and succeeded by a translation the panel's center. Note that the operations are performed in the apparent reverse of the declared order. Your example (may have meant to) invoke rotate(double theta, double anchorx, double anchory). The two effect the same result, the latter being a convenient alternative to the former.
This example contrasts how one can transform the graphics context (g2d) or the image itself. Your example invokes drawImage(Image img, AffineTransform xform, ImageObserver obs), which concatenates xform to the existing graphics transform; this affects all subsequent drawing. It may be easier to keep them separate.

Combining rotations and translations - Java 2D

public void drawEarth(Graphics2D g2){
theta -=0.1;
g2.rotate(theta);
g2.translate(50, 50);
g2.setPaint(Color.blue);
g2.fill(shape);
}
public void rotate(Graphics2D g2)
{
theta -=0.1;
g2.translate(50, 50);
g2.rotate(theta);
}
I've written these two methods. The first one causes the shape to revolve around a point, and I'm now trying to make the shape spin about its axis. I've been told that doing translation before rotation would allow the shape to spin about it's axis (as shown in the second method), but I'm not sure how to combine these two translations so that it revolves and rotates?
Any help is much appreciated.
There is too many smart words to me but maybe you want do this:
g2.rotate(double theta, double x, double y)
rotate in documentation:
Concatenates the current Graphics2D
Transform with a translated rotation
transform.
For an object it works like this: An object always rotates around the Origin.
And it also works like this Scale --> Rotate --> Translate.
If you want to rotate an object around its own axis, it has to be on the origin (which it is when you don't translate). Just call a rotate first and then translate it into the world. Once you have done that, you have to rotate it around your earth. So call a rotate again.
So you get this: (Scale) --> Rotate on own axis --> Translate on own offset --> Translate to the earth --> Rotate around the earth
I hope this helps. I don't know about the java API for this, but only about the general viewing pipeline.

Can we tilt a JPanel at an angle?

I have image inside the JPanel. I would like to rotate the image. Is it possible to rotate the JPanel using Graphics, Image is rotatable, Just out of curiosity is it possible to rotate JPanel ?
Yes! This is possible and fairly straightforward too. I haven't done rotations but I have done other affine transformations (scaling the entire GUI up and down) very successfully on a project. I cannot see why rotations should be any different.
Instead of trying to scale each component use the fact that you can set a transformation on the Graphics object. Since this is shared between all components being rendered you get all things transformed at once "for free". It is important to realize that the transformation is only a rendering-process-step ... i.e. all components still believe they have the bounds (locations+sizes) which you gave them in the untransformed world. This leaves us with the challenge to deal with mouse-events correctly. To do this you simply add a glass-pane in front of your main-panel. This pane collects all mouse-events and apply a reverse of the transform on the event and then sends the event onward towards all other components.
Conceptually very simple! Still, I remember it took some tweaking to get it all crisp though. Especially the fact that rendered texts (fonts) in java are not correctly linearly scaled (it scales in discrete steps corresponding to font-sizes) imposed a final challenge in my scale-affine-transformation-case. Maybe you don't have to worry about that if you only rotate.
I got my inspiration from JXTransformer: http://www.java.net/blog/alexfromsun/archive/2006/07/jxtransformer_t.html
As far as I know you can't rotate a JPanel itself but you might be able to rotate the image inside the JPanel using Java2D. Here's an article that might help.
Edit:
There might actually be a way to rotate JComponents (such as JPanel) if you override their paintXxx methods and use AffineTransform.
It's not possible to rotate JPanel itself, but it's certainly possible to rotate any image inside. There are quite a few ways to do that, you can - for example - override JPanel's public void paint(Graphics g) and then cast Graphics to Graphics2D. It's very useful class, does rotation and much more ;) Check api docs for more info about this one.
Yes, it is possible. But you won't rotate the panel, but the image:
public void paintComponent(Graphics gg)
{
Graphics2D g = (Graphics2D) gg;
g.setRenderingHint(RenderingHints.KEY_ANTI_ALIAS, RenderingHints.VALUE_ANTI_ALIAS_ON);
AfflineTransform matrix = g.getTransform(); // Backup
float angle = Math.PI / 4.0f; // 45°
g.rotate(angle);
/* Begin */
g.drawImage(yourImage, [your coordinates], null);
/* End */
g.setTranform(matrix); // Restore
}
Everything between /* Begin */ and /* End */ will be drawn rotated.
(I didn't test the code, so, they may be some syntax errors...)

Cannot get image to move where I want it to (and update continuously)?

I'm Basically programming a simple game engine but I'm having problems with my sprites/images not appearing when they should... or at all!
I'll try and keep this as simple as possible. I have a Sprite, GameEngine and Display class. In the gameloop, I have a method that sets the new position of my Sprite (so it just sets the x and y variables). Next I call a transform method which does the following:
public void transform() {
affineTransform.setToIdentity();
affineTransform.translate(x, y);
}
Following that, I then call a draw method in the Sprite:
public void draw() {
graphics2D.drawImage(image, affineTransform, jFrame);
}
Finally, in my thread I then call repaint() on the JFrame (the Display class). My paint method for that class is as follows:
public void paint(Graphics g) {
g.drawImage(backbuffer, insets.left, insets.top, this);
}
But nothing is appearing, apart from a black screen!
I'm also getting confused between Graphics g, and Graphics2D and when to use either. (The overridden paint method uses Graphics g). For the record, I do have a Graphics2D variable in the class that is created by calling backbuffer.createGraphics();
Another thing that is confusing me is this AffineTransform... I've read the documentation but I'm still utterly confused on how and when to use it - and what exactly it seems to do. Is there any explanation in relatively simple terms?
Surely this should be working... am I missing something out here?
To answer part of your question:
From the Graphics2D JavaDoc
This Graphics2D class extends the Graphics class to provide more sophisticated control over geometry, coordinate transformations, color management, and text layout. This is the fundamental class for rendering 2-dimensional shapes, text and images on the Java(tm) platform.
Essentially, with Graphics2D you can do much more than you can with Graphics. And with a Sun JVM 1.5+, it should be safe to cast the Graphics object you get in paint() to Graphics2D
I just noticed this: For the record, I do have a Graphics2D variable in the class that is created by calling backbuffer.createGraphics();
You should make sure you're not drawing on a Graphics[2D] canvas (I'll use this term to refer to the drawable area that the Graphics[2D] object provides) that you later throw away. If you're drawing your image on a separate canvas, you should ensure that you then draw that image onto your actual display canvas.
I don't really have a good explanation of AffineTransform but maybe these will help?
http://www.javalobby.org/java/forums/t19387.html
https://secure.wikimedia.org/wikipedia/en/wiki/Affine_transformation
From Wikipedia - In general, an affine transformation is composed of linear transformations (rotation, scaling or shear) and a translation (or "shift"). Several linear transformations can be combined into a single one. Basically, you use this class to perform operations such as rotation, translation, zoom etc.

Categories