Rotating Java 2D Graphics Around Specified Point

为君一笑 提交于 2019-11-30 19:41:47

问题


I'm trying to write a program that will draw several shapes rotated around a center point. The result should be something like a Spirograph. I'm trying to test it using rectangles but I can only get two of them to appear in the window. One of them is where it should be, but then after the first rotation it throws the other square way up in the top left corner of the window. It should be rotated and drawn around the center point. Here is a portion of my code.

import java.awt.*;
import java.awt.geom.Ellipse2D;

import javax.swing.JPanel;

public class Shapes extends JPanel
{
private double angle;
private int type;
private int radius;
private int repeats;

public Shapes(int t, int r, int z)
{
   type = t;
   radius = r;
   repeats = z;      
   angle = 360 / repeats;
}

public void paintComponent( Graphics g )
{
  super.paintComponent( g );
  Graphics2D g2d = (Graphics2D)g;

  g.setColor(Color.red);

  int centerX = getWidth()/2;
  int centerY = getHeight()/2;

  double curAngle = 0;

  for(int i=0; i<=repeats; i+=1)
  {
      g.setColor(Color.blue);

      Rectangle tangle = new Rectangle(0, 0, radius, radius);
      g2d.rotate(Math.toRadians(curAngle));
      g2d.translate(centerX, centerY);
      g2d.draw(tangle);
      curAngle += angle;
  }

}


回答1:


Remember, translate and rotate are compounding, that is, each time you apply them, they add to the current transformation.

There are a number of ways you might be able to achieve this, but first, we need to make a copy of the Graphics context. It's kind of important any time you mess with the transform in particular, you do so with a copy of the Graphics context, as this will leave the original unaffected (and won't effect anything that might be painted after)

Graphics2D g2d = (Graphics2D) g.create();
//...
g2d.dispose();

So anything you do to g2d now, won't affect the state of g

Now, we can use the "compounding" effect of a transform to our advantage

Rectangle tangle = new Rectangle(0, 0, radius, radius);
//g2d.translate(centerX, centerY);
g2d.rotate(Math.toRadians(angle), centerX, centerY);
g2d.draw(tangle);

So, all this does is applies the value of angle to the copy of the Graphics context on each loop. The anchor point is set to the centerX and centerY points

Okay, that looks okay, but what happens if I resize the window?

Okay, not really what I was expecting. This occurs for a combination of reasons, the size of the shape, the anchor point, the rotation, the translation offset, these are all compounding to produce the effect (cool though).

Okay, so, instead, we can simply create a new transform for each loop instead, supplying the exact parameters we want, for example...

Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.blue);

Rectangle tangle = new Rectangle(0, 0, radius, radius);
g2d.translate(centerX, centerY);
g2d.rotate(Math.toRadians(curAngle));
g2d.draw(tangle);
curAngle += angle;
g2d.dispose();

This now produces...

While playing around with the code, I noticed that as I increased the number of repeats, I wasn't getting the desired results.

After same digging, I changed

angle = 360 / repeats;

to

angle = 360.d / repeats;

which stopped the integer division issue (and truncating of the decimal values) and started to produce the desired results

A simple before and after comparison...



来源:https://stackoverflow.com/questions/32513508/rotating-java-2d-graphics-around-specified-point

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!