Search code examples
javarotationaffinetransform

How to rotate shape from its center as well as from center of the screen


I have created Star shape using drawPolygon() but I want to rotate it from the center point of the star as well as from center of the screen.

Here is my code to rotate star from its center:

@Override
public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    AffineTransform origX = g2d.getTransform();
    AffineTransform newX = (AffineTransform) origX.clone();
    newX.rotate(Math.toRadians(angle), x, y + 62);  // Rotate about center of the star
    g2d.setTransform(newX);
    g2d.drawPolygon(starX, starY, 5);
    g2d.dispose();
    g.dispose();
}

If i replace:

newX.rotate(Math.toRadians(angle), x, y + 62);

to

newX.rotate(Math.toRadians(angle), this.getWidth() / 2, this.getHeight() / 2);

I can able to rotate it from center of the screen.

However, I want to achieve both the effects simultaneously. i.e.: Like the earth which rotate around the sun as well as its own axis.

I have tried creating another AffineTransform object but it overwrite the previous one when I set it using g2d.setTransform(newObj);

Any suggestions will be extremely helpful. Thank you.

Here is my complete code if you want to see

import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;

public class Star extends Applet implements Runnable{
  private int[] starX;
  private int[] starY;
  private Thread mainThread;
  private int x;
  private int y;
  private int angleFromCenterShape;

  @Override
  public void init() {
    this.setSize(800, 480);
    x = 250;
    y = 150;
    angleFromCenterShape = 0;
    starX = new int[5];
    starY = new int[5];
    mainThread = new Thread(this);
    mainThread.start();
    this.setBackground(Color.BLACK);
  }

  @Override
  public void paint(Graphics g) {
    Graphics2D g2d = (Graphics2D) g;
    AffineTransform origX = g2d.getTransform();
    AffineTransform newX = (AffineTransform) origX.clone();
    newX.rotate(Math.toRadians(angleFromCenterShape), x, y + 65);   //Rotate about center of the star
    g2d.setTransform(newX);
    g2d.setColor(Color.red);
    g2d.fillPolygon(starX, starY, 5);
    g2d.dispose();
    g.dispose();
  }

  @Override
  public void run() {
    while(true){
        angleFromCenterScreen = (angleFromCenterScreen + 1) % 360; // angle loop from 0 to 36o
        initStar();
        try{
            Thread.sleep(30);
        }catch(Exception e){}
        repaint();
    }
  }

  private void initStar(){
    starX[0] = x;
    starX[1] = x - 50;
    starX[2] = x + 75;
    starX[3] = x - 75;
    starX[4] = x + 50;
    starY[0] = y;
    starY[1] = y + 130;
    starY[2] = y + 50;
    starY[3] = y + 50;
    starY[4] = y + 130;
  }
}

Solution

  • I have found a workaround for my problem but it is not an exact solution. However adding another rotate() on the same AffineTransform object mimic the 2 rotations

    Here is the code

    @Override
      public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        AffineTransform origX = g2d.getTransform();
        AffineTransform newX = (AffineTransform) origX.clone();
        newX.rotate(Math.toRadians(angle), this.getWidth() / 2, this.getHeight() / 2);  // Rotate from the center of screen
        newX.rotate(Math.toRadians(angle), x, y + 65);   // Rotate from the center of the shape
        g2d.setTransform(newX);
        g2d.setColor(Color.red);
        g2d.fillPolygon(starX, starY, 5);
        g2d.dispose();
        g.dispose();
      }