在指定点周围旋转Java 2D图形

我正在尝试编写一个程序,它将绘制围绕中心点旋转的几个形状。 结果应该像Spirograph。 我正在尝试使用矩形测试它,但我只能让其中两个出现在窗口中。 其中一个应该是它应该在的位置,但是在第一次旋转之后,它将另一个方向向上抛出窗口的左上角。 它应该围绕中心点旋转和绘制。 这是我的一部分代码。

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; } 

}

请记住, translaterotate是复合的,也就是说,每次应用它们时,它们都会添加到当前的转换中。

您可以通过多种方式实现此目标,但首先,我们需要复制Graphics上下文。 在你特别乱搞变换的时候这很重要,你用Graphics上下文的副本这样做,因为这会使原始版本不受影响(并且不会影响之后可能被绘制的任何内容)

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

所以你现在对g2d做的任何事都不会影响g的状态

现在,我们可以利用变换的“复合”效应来发挥我们的优势

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

因此,所有这一切都将angle值应用于每个循环上的Graphics上下文的副本。 锚点设置为centerXcenterY

螺旋01

好吧,看起来没问题,但如果我调整窗口大小会怎样?

螺旋02

好吧,不是我所期待的。 出现这种情况的原因有多种,形状大小,锚点,旋转,平移偏移,这些都是复合产生效果(尽管很酷)。

好的,相反,我们可以简单地为每个循环创建一个新的变换,提供我们想要的确切参数,例如……

 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(); 

这现在产生……

螺旋03

在玩代码时,我注意到随着我增加重复次数,我没有得到预期的结果。

经过同样的挖掘,我改变了

 angle = 360 / repeats; 

 angle = 360.d / repeats; 

它停止整数除法问题(并截断小数值)并开始产生所需的结果

比较之前和之后的简单……

之前 后