Rotating a Rectangle on an Image using Swing - java

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.

Related

How to draw a sector of a BufferedImage?

I'm making a game with a mouse cursor, and I'd like to represent the health by overlaying the cursor with a green version of the image, but only a geometric sector of it corresponding to the health percentage. Solutions from posts like these: Drawing slices of a circle in java? & How to draw portions of circles based on percentages in Graphics2D? are pretty much what I want to do, but with a BufferedImage as opposed to a solid color fill.
//Unfortunately all this does is cause nothing to draw, but commenting this out allows the overlay image to draw
Arc2D.Double clip = new Arc2D.Double(Arc2D.PIE);
double healthAngle = Math.toRadians((((Double)data.get("health")).doubleValue() * 360.0 / 100.0) - 270.0);
clip.setAngles(0, -1, Math.cos(healthAngle), Math.sin(healthAngle));
System.out.println(Math.cos(healthAngle) + " " + Math.sin(healthAngle));
g.setClip(clip);
In short, how do I draw a sector of a BufferedImage given any angle?
If you read the API docs for setClip(Shape) you'll see that the only shape that is guaranteed to work, is a rectangle. So, setting the clip probably won't work.
However, there are other options. The most obvious is probably to use a TexturePaint to fill your arc with the BufferedImage. Something like:
TexturePaint healthTexture = new TexturePaint(healthImg, new Rectangle(x, y, w, h));
g.setPaint(healthTexture);
g.fill(arc); // "arc" is same as you used for "clip" above
Another option is to first draw the arc in solid color, over a transparent background, then paint the image over that, using the SRC_IN Porter-Duff mode. Something like:
g.setPaint(Color.WHITE);
g.fill(arc); // arc is same as your clip
g.setComposite(AlphaComposite.SrcIn); // (default is SrcOver)
g.drawImage(x, y, healthImg, null);

How to rotate sprite via draw method

I have not found answer for this question anywhere, so let's go.
What i expect:
I want to render rocket. Rocket is flying from given start point with evaluated angle. I'm evaluating angle like this:
getVelocity().angle() - 90f
My problem is to calibrate rocket position on top of the rocket. Image below shows how should it work:
In the top picture is how libgdx render not rotated texture region. In the bottom picture is what i expect: I want to move and rotate texture region with given angle to have (x,y) coordinate on the top of rocket.
What i have:
I tired to write method to draw sprite how i expect but i failed. I think it is caused due to fact that i don't understand documentation of this method.
Following manual:
void com.badlogic.gdx.graphics.g2d.SpriteBatch.draw(TextureRegion region, float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation)
Draws a rectangle with the bottom left corner at x,y and stretching the region to cover the given width and height. The rectangle is offset by originX, originY relative to the origin. Scale specifies the scaling factor by which the rectangle should be scaled around originX, originY. Rotation specifies the angle of counter clockwise rotation of the rectangle around originX, originY.
My code:
public static void drawRotatedTex(SpriteBatch pmRenderer, TextureRegion pmTex, float pmPosX, float pmPosY, float pmAngle)
{
pmRenderer.begin();
pmRenderer.draw(
pmTex, pmPosX, pmPosY, -pmTex.getRegionWidth()/2, pmTex.getRegionHeight(), pmTex.getRegionWidth(), pmTex.getRegionHeight(), 1f, 1f, pmAngle);
pmRenderer.end();
}
Results:
It is moment of collision. As we can see coordinates are offset in relation to rocket.
I don't ask about full solution. For me will be sufficient if someone explain me (on drawing or something) like this method works.
EDIT
Moderation suggested that this question is duplicate of:
libgdx: Rotate a texture when drawing it with spritebatch
I read this topic, but it is not my solution. I know how to rotate my sprite by i don't have idea why coordinates of rocket are offset in relation to rocket top.
EDIT
Invocation of my drawRotatedTex from rocket class:
#Override
public void render(Renderer pmRenderer, float pmX, float pmY) {
SpriteBatch lvSpritebatch = pmRenderer.getSpriteBatch();
Sprite lvSprite = null;
if(mIsExploding)
{
if((lvSprite = mExplosion.getTexture()) != null)
{
lvSpritebatch.begin();
lvSpritebatch.draw(lvSprite, pmX + lvSprite.getWidth()/2, pmY - lvSprite.getHeight()/2);
lvSpritebatch.end();
}
}
else
{
lvSprite = mAnimation.getTexture();
RendererTools.drawRotatedTex(lvSpritebatch,lvSprite,pmX,pmY,getVelocity().angle() - 90f);
}
}
It is not very clear what you are asking, if it's only about moving the origin you would not need that much text. Anyway, I will take a shot at it.
If you want to accomplish what you have in your picture you setup your sprite like this:
sprite.setOrigin(s.getWidth()/2, s.getHeight()); //Centers sprite on top of image.
If I now rotate it in the draw method it rotates around the top center.
sprite.rotate(5);
sprite.draw(batch);
Despite being rotated around the center top of itself it remains position remains the same. If I would set the origin far away from the image and rotate it then the image would travel very far but the position remains the same. Still if you would move it's position 10 pixels to the right the image (wherever it may be) will be moved to the right.
Hope this helps.

Draw the rectangle and fill the rectangle based on (x,y) points

I was not able to figure out how to fill the drawn rectangle based on (x,y) points. Basically inside (x,y) points. There can be a array of (x,y) points.
Anyone can help on this.....
Rectangle r = new Rectange(length, width, x, y);
r.fill(Color.yourColor);
Graphics g = getGraphics();
g.draw(r);

Image Quality Gets Ruined In Java Graphics2D Rotate

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.

Image not drawn to a fixed position when rotating with AffineTransform

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.

Categories