Results 1 to 7 of 7
  1. #1
    Lance is offline Member
    Join Date
    Feb 2011
    Posts
    3
    Rep Power
    0

    Default Rotating Rectangle about its Centre

    Hi all,

    I'm trying to get to grips with drawing graphics in Java at the moment so I've decided to try and draw a rectangle on the screen and allow the user to move and rotate it using keyboard keys.

    I've been able to do most of it, but now I'm stuck on the rotation of the rectangle in that it doesn't rotate correctly as it rotates about a point in the screen (where the rectangle is initially drawn) and not its central point. It's a bit difficult to explain in text but if you imagine a rectangle being created at the centre of a clock face and then moved to the edge (at say 3) when you try and rotate the rectangle it pivots on the centre of the clock face and not its own centre.

    Basically, I want to always rotate the rectangle about its centre point only. I understand that using the translate and rotate methods actually moves the whole co-ordinate system not just the rectangle so I guess my question is how after rotating and translating can I restore the coordinate system back to as it was before I did anything (translate, rotate)?

    Here is my code:
    Java Code:
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.awt.geom.*;
    
    public class ShapeExample extends JPanel implements KeyListener {
    
        int x;
        int y;
        double rotation;
    
        public ShapeExample() {
            setFocusable(true);
            addKeyListener(this);
            setDoubleBuffered(true);
        }
    
        @Override
        public void paintComponent(Graphics g) {
            AffineTransform saveTransform;
            final Graphics2D g2 = (Graphics2D) g;
    
            g.clearRect(0, 0, this.getWidth(), this.getHeight());
    
            Rectangle rect = new Rectangle(20, 20);
    
            g2.rotate(Math.toRadians(rotation), rect.height / 2, rect.width / 2);
            g2.translate(x, y);
    
            g2.draw(rect);
    
        }
    
        public static void main(String[] args) {
            WindowUtilities.openInJFrame(new ShapeExample(), 380, 400);
        }
    
        public void keyTyped(KeyEvent e) {
        }
    
        /** Handle the key-pressed event from the text field. */
        public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) {
                case KeyEvent.VK_LEFT:
                    x = x - 5;
                    repaint();
                    break;
                case KeyEvent.VK_RIGHT:
                    x = x + 5;
                    repaint();
                    break;
                case KeyEvent.VK_UP:
                    y = y - 5;
                    repaint();
                    break;
                case KeyEvent.VK_DOWN:
                    y = y + 5;
                    repaint();
                    break;
                case KeyEvent.VK_X:
                    rotation++;
                    repaint();
                    break;
                case KeyEvent.VK_Z:
                    rotation--;
                    repaint();
                    break;
    
            }
        }
    
        public void keyReleased(KeyEvent e) {
        }
    }

  2. #2
    doWhile is offline Moderator
    Join Date
    Jul 2010
    Location
    California
    Posts
    1,641
    Rep Power
    7

    Default

    Take a look at the API for the rotate Graphics2D method you are using...it translates, rotates, and -translates. Shouldn't be a need to call translate again (edit: nevermind, I think I misunderstood your initial intent). To reverse the rotation for future draw calls, just call g2.rotate on the negative of the rotation magnitude from the first call.
    Last edited by doWhile; 02-15-2011 at 12:20 AM.

  3. #3
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

  4. #4
    Lance is offline Member
    Join Date
    Feb 2011
    Posts
    3
    Rep Power
    0

    Default

    Quote Originally Posted by doWhile View Post
    Take a look at the API for the rotate Graphics2D method you are using...it translates, rotates, and -translates. Shouldn't be a need to call translate again (edit: nevermind, I think I misunderstood your initial intent). To reverse the rotation for future draw calls, just call g2.rotate on the negative of the rotation magnitude from the first call.

    So something like save the rotation variable before any rotation takes place i.e. originalRotation and then call the rotate method with the originalRotation as a parameter?


    Quote Originally Posted by Fubarable View Post
    Have you tried to use x and y and basic algebra to find the new center point of the rectangle?

    I think I tried this by calling the rotate method and passing it the y and x values for the centre of the rectangle and it didn't work.
    The way I understood the issue is the rectangle isn't actually moving its just the co-ordinate system that is and the rectangle remains fixed with regards to the co-ordinate system meaning the rectangles coordinates never actually change.
    I was using this tutorial 2. Ordering which shows the x and y axis rotating.

    I'm not that great at maths which is probably part of the reason I'm struggling with this! I appreciate the replies, thank you.

  5. #5
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    First, rotate by the amount you want. Then translate. The amount you need to translate is determined as follows:

    - compute the distance, d, to the center of the rectangle from 0, d = sqrt((x+w/2)^2 + (y+h/2)^2)

    - the amount of x translation is 2d*cos((pi-angle)/2)
    - the amount of y translation is 2d*sin((pi-angle)/2)

    (I might have the sign backward on one or both)
    Last edited by toadaly; 02-15-2011 at 07:01 AM.

  6. #6
    Lance is offline Member
    Join Date
    Feb 2011
    Posts
    3
    Rep Power
    0

    Default

    It's been a while since I've worked on this but I was able to achieve the movement I wanted; which was get a rectangle to move in a certain direction, rotate about its centre and then move in the new direction. I did it by using an 'AffineTransform'. I applied the translate and rotate methods to the 'AffineTransform' and then set the Graphics component to this transform after both the translate and rotate methods had been called. Then finally calling the draw method on the rectangle.

    I just have one last issue in that I don't fully understand the trigonometry i've used to compute the movement of the rectangle. I understand that movement in a certain direction (i.e. at a certain angle) can be defined by the rate of change of the x value of the object in relation to the y value of the object. What I don't understand is what the sin and cos functions are actually doing.

    What I'm really asking for is an explanation of the formulas in toadalys post:

    - the amount of x translation is 2d*cos((pi-angle)/2)
    - the amount of y translation is 2d*sin((pi-angle)/2)

    I've been reading about trigonometry with regards to right angle triangles but I don't get what the above is actually doing, specifically the '(pi-angle)/2' bit.

  7. #7
    toadaly is offline Senior Member
    Join Date
    Jan 2009
    Posts
    671
    Rep Power
    6

    Default

    If you don't know basic trig, it's going to be hard to explain the translation terms. But, here's how you can figure it out yourself assuming you do understand basic geometry and trig:

    - draw an x/y axis
    - draw a rectangle on it somewhere, label the center of the rectangle x0,y0
    - draw a rotated x/y axis, rotating about the 0,0 point, label the amount of rotation 'angle'
    - examine where your rectangle is relative to the new axis
    - by drawing the correct right triangles, you'll be able to figure out the new center point relative to the original center point x0,y0

    ....and I might have got it wrong

Similar Threads

  1. Replies: 6
    Last Post: 12-01-2010, 12:29 AM
  2. Wrong with Rectangle res = new Rectangle(0,0,0,0);???
    By jiapei100 in forum AWT / Swing
    Replies: 3
    Last Post: 09-25-2010, 04:39 PM
  3. Rotating Images
    By Unome in forum Java Applets
    Replies: 3
    Last Post: 03-30-2009, 05:55 PM
  4. Rotating an image
    By lackofcolor in forum Java 2D
    Replies: 3
    Last Post: 02-28-2009, 12:54 AM
  5. Rotating Image?
    By sciguy77 in forum Java Applets
    Replies: 9
    Last Post: 02-17-2009, 02:47 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •