I have a problem with rotating image in a fixed position with Graphcis2D and AffineTransform.
The idea is to rotate an image according to body's rotation.
The rotation is happening correctly as the rotation angle of the image matches the angle of the body's rotation. However, as the rotation takes place, the image is not drawn to the same position as the body should be drawn. The code of the method painting the picture is the following:
public void paintPicture(Graphics g, Body body) {
Graphics2D g2 = (Graphics2D) g;
Vector2f[] vertices = ((Box) body.getShape()).getPoints(body.getPosition(), body.getRotation());
Vector2f topLeftCorner = vertices[0];
AffineTransform oldTransform = g2.getTransform();
AffineTransform at = new AffineTransform();
at.rotate(body.getRotation());
g2.setTransform(at);
g2.drawImage(this.img, (int) topLeftCorner.x, (int) topLeftCorner.y, null);
g2.setTransform(oldTransform);
}
Any ideas what might cause the movement of the image instead of drawing it according to the coordinates (topLeftCorner.x, topLeftCorner.y)?
You need to first translate you object so the anchor point (the point around which you want it to rotate) is at the origin, perform your rotation, then translate it back. So if you want to rotate around the point (50, 75), you'd do the following:
at.translate (-50, -75);
at.rotate (body.getRotation());
at.translate (50, 75);
I'm assuming that your AffineTransform class can accumulate transformations. If not, you'll need 3 different transforms.
Related
I would like to rotate, scale, and translate a section of an image. For example, I have a sprite-sheet with columns and rows of sprites. I can draw the section I want onto a temporary BufferedImage, then transform that temporary image onto the main graphics, but this is a very slow operation.
How can I make this much much faster? It needs to occur more than 100 * 60 times per second.
public void Draw_WorldSpace(Graphics2D g, double x, double y, double angle, double deltaTime) {
// setup portion of image to transform
BufferedImage tempImage = new BufferedImage(sourceRectangle.width, sourceRectangle.height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = tempImage.createGraphics();
g2.drawImage(image, 0, 0, sourceRectangle.width, sourceRectangle.height, sourceRectangle.x, sourceRectangle.y, sourceRectangle.width, sourceRectangle.height, null);
g2.dispose();
// setup a transformation object
AffineTransform transform = new AffineTransform();
// match view rotation
transform.translate(GameLogic.viewPort.GetCanvasCenter().x, GameLogic.viewPort.GetCanvasCenter().y);
transform.rotate(Math.toRadians(GameLogic.viewPort.GetAngle()));
transform.translate(-GameLogic.viewPort.GetCanvasCenter().x, -GameLogic.viewPort.GetCanvasCenter().y);
// set to position
transform.translate(x - GameLogic.viewPort.GetViewPortCenter().x + GameLogic.viewPort.GetCanvasCenter().x, y - GameLogic.viewPort.GetViewPortCenter().y + GameLogic.viewPort.GetCanvasCenter().y);
// rotate
transform.rotate(Math.toRadians(angle));
// center on sprite
transform.translate(-sourceRectangle.width / 2, -sourceRectangle.height() / 2);
// draw the sprite
g.drawImage(tempImage, transform, null);
}
Ultimately I did what Hovercraft Full Of Eels suggested. I wasn't the biggest fan of the solution simply because it requires a lot of memory overhead. But ultimately, it worked like a charm and even game me more streamlined control over the graphics, so that's really cool.
I want to roatate an Image with Affinetransform
I did it like this:
AffineTransform at = AffineTransform.getTranslateInstance(image.getWidth(null), image.getHeight(null));
at.rotate(Math.toRadians(getRadian()),image.getWidth(null)/2, image.getHeight(null)/2);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image, at, null);
But now I want to set the Position of the Image,how do I do this?
Thanks for help
First of all it's unclear which position of image you want to translate to necessary place. Let me propose general rule. Suppose that you want to be able to rotate image around its internal coordinates (ix,iy) and then place this internal position to new global place with coordinates (gx, gy). And rotation angle is "angleInRadians". Then your transformation will be:
AffineTransform at = AffineTransform.getTranslateInstance(gx, gy);
at.rotate(angleInRadians);
at.translate(-ix, -iy);
Do you see back order of events here? It's because of how transformation matrices are applied to each other and to position vector. If you read this from the end to beginning then what we do is we move internal position to coordinate start, then we rotate around this start and then we move this start to necessary global place.
If you need to move center of image then:
double ix = imageWidth / 2;
double iy = imageHeight / 2;
If you want to move left upper corner then ix = 0 and iy = 0, so you can skip at.translate(-ix, -iy) in this case.
I am passing in an object for Android to paint using it's canvas. The object to rotated to match the horizon. I am trying to find the translated points which canvas calculates given the point and angle I give it.
For example:
I use the following canvas methods to paint it. Where x,y are the screen coordinates and rotation is the rotation of the screen relative to the horizon.
canvas.save();
canvas.translate(x,y);
canvas.rotate(rotation);
obj.paint(canvas);
canvas.restore();
obj.paint() looks like this (but you probably don't need to know it):
canvas.save();
canvas.translate(-width/2, -height/2);
setFill(true);
setColor(backgroundColor);
paintRect(canvas, x, y, width, height);
setFill(false);
setColor(borderColor);
paintRect(canvas, x, y, width, height);
canvas.restore();
paintRect() looks like this:
canvas.drawRect(x, y, x + width, y + height, paint);
What I am trying to figure out is; what are the corner points of the rectangle (green in this picture) after it has been rotated.
Here is an image of the result which is what I expect.
I am experiencing an issue with rotating an Image with the Graphics2D rotate method.
Here's an image of the issue I'm having:
As I move the ball, the image gets completely distorted as it rotates.
Here's my rotate method:
public static void rotate(BufferedImage img, Rectangle rect, int degrees) {
Graphics2D g = (Graphics2D) img.createGraphics();
g.rotate(degrees, rect.x + rect.width/2, rect.y + rect.height/2);
g.drawImage(img, rect.x, rect.y, rect.width, rect.height, null);
g.dispose();
}
Is there anything I can do to avoid the quality loss?
So currently as the ball moves, you rotate the image a few degrees and overwrite the original image with the new one? Each time the image is rotated, a tiny bit of distortion is added; over many rotations, the distortion is compounded.
Instead, just keep the original image in memory and also store the number of degrees it should appear to be rotated on screen. Then each time you render it, rotate the original image by the current number of degrees.
I know this is a pretty old question but for anyone looking to do something similar try putting the following code before your g.drawImage
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
That should help to make the image look a better.
Ok when a user draws a Rectangle on top of an image, I want to find all the rotated Rectangles ahead of time for all image rotation angles (90,180,270,360).
According to Java API I can just keep calling the Graphics2D rotate() method. I can then use this Graphics2D transformer to get the rotated Rectangle.
This works for the very first rotation(1.5708) call. I get the correct Rectangle Point. All other calls after that return the wrong Rectangle Point after using Transformer.
I think my problem is the Graphics2D translate(x,y). I don't understand how to use it.
Anyone knows how to fix my code so that it will return the correct Rectangle after every rotation?
Thank you.
public void rotateRectangles(BufferedImage bim,int width,int height,Rectangle rect){
BufferedImage bim = new BufferedImage(height, width,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D) (bufferedImage.createGraphics());
g2d.translate(bufferedImage.getHeight(),0);
//Get Rectangle for 90 degree image rotation. This always good.
g2d.rotate(1.5708);
Shape shape = g2d.getTransform().createTransformedShape(rect);
Rectangle rotatedRect = shape.getBounds();
System.out.println("rotated rectangle at 90 degrees. Point x="+rotatedRect.x+" y="+rotatedRect.y);
//Get Rectangle for 180 degree image rotation. Getting wrong rotatedRect.
g2d.rotate(1.5708);
shape = g2d.getTransform().createTransformedShape(rect);
rotatedRect = shape.getBounds();
System.out.println("rotated rectangle at 180 degrees. Point x="+rotatedRect.x+" y="+rotatedRect.y);
//Get Rectangle for 270 degree image rotation. Getting wrong rotatedRect.
g2d.rotate(1.5708);
shape = g2d.getTransform().createTransformedShape(rect);
rotatedRect = shape.getBounds();
System.out.println("rotated rectangle at 270 degrees. Point x="+rotatedRect.x+" y="+rotatedRect.y);
//Get Rectangle for 360 degree image rotation.Getting wrong rotatedRect.
g2d.rotate(1.5708);
shape = g2d.getTransform().createTransformedShape(rect);
rotatedRect = shape.getBounds();
System.out.println("rotated rectangle at 360 degrees. Point x="+rotatedRect.x+" y="+rotatedRect.y);
}
Thank you.
Instead of rotating the graphics context's affine transform via g2d.rotate(), consider using createTransformedShape() as suggested in this example.
Addendum: Note in particular that the baseline of the example Polygon is initially centered on the origin. As a result, the initial transformation is rotation around the origin. In your case, you can use the rotate() method that includes an anchor point, which would be the center of your rectangle.