Hallo zusammen,
im folgenden Beispiel sind vier JComponents zu sehen, in deren paintComponent jeweils ein Rechteck mehrfach in verschiedenen Orientierungen gezeichnet wird. Die Orientierungen werden durch Anwendung von AffineTransform-Instanzen umgesetzt.
Laut der API Dokumentation ()https://docs.oracle.com/javase/7/docs/api/java/awt/geom/AffineTransform.html#getRotateInstance(double, double, double) hätte ich erwartet, dass eine Rotation um einen bestimmten Ankerpunkt dasselbe Ergebnis liefert wie die Kombination aus Translation zum Ursprung, Rotation, und Translation zurück zu den entsprechenden Korodinaten. In dem Beispiel ist aber deutlich zu erkennen, dass dem nicht so ist. Die Rotation um den Ankerpunkt führt zum erwarteten Ergebnis, die Kombination aus Translation, Rotation,und Translation aber nicht. Dabei macht es ausserdem einen Unterschied, ob die Transformationen verknüpft werden, oder auf dem Graphics2D die Kommandos zur Translation und Rotation aufgerufen werden, was meiner Meinung nach auch nicht sein dürfte.
Kann mir jemand das Verhalten erklären?
im folgenden Beispiel sind vier JComponents zu sehen, in deren paintComponent jeweils ein Rechteck mehrfach in verschiedenen Orientierungen gezeichnet wird. Die Orientierungen werden durch Anwendung von AffineTransform-Instanzen umgesetzt.
Laut der API Dokumentation ()https://docs.oracle.com/javase/7/docs/api/java/awt/geom/AffineTransform.html#getRotateInstance(double, double, double) hätte ich erwartet, dass eine Rotation um einen bestimmten Ankerpunkt dasselbe Ergebnis liefert wie die Kombination aus Translation zum Ursprung, Rotation, und Translation zurück zu den entsprechenden Korodinaten. In dem Beispiel ist aber deutlich zu erkennen, dass dem nicht so ist. Die Rotation um den Ankerpunkt führt zum erwarteten Ergebnis, die Kombination aus Translation, Rotation,und Translation aber nicht. Dabei macht es ausserdem einen Unterschied, ob die Transformationen verknüpft werden, oder auf dem Graphics2D die Kommandos zur Translation und Rotation aufgerufen werden, was meiner Meinung nach auch nicht sein dürfte.
Kann mir jemand das Verhalten erklären?
Java:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.geom.AffineTransform;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class AffineTransformTest extends JComponent {
private boolean combineTransforms;
private boolean modifyG2;
public static void main(String[] args) {
JFrame frame = new JFrame("Affine Transform Test");
JPanel panel = new JPanel(new GridLayout(2, 2));
panel.add(new AffineTransformTest(false, false));
panel.add(new AffineTransformTest(true, false));
panel.add(new AffineTransformTest(false, true));
panel.add(new AffineTransformTest(true, true));
frame.setContentPane(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public AffineTransformTest(boolean combine, boolean modify) {
super();
this.combineTransforms = combine;
this.modifyG2 = modify;
setPreferredSize(new Dimension(600, 600));
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
AffineTransform oldAT = g2.getTransform();
Rectangle rect = super.getBounds();
Rectangle2D.Double master = new Rectangle2D.Double(50, 50, 200, 300);
Rectangle2D.Double slave = new Rectangle2D.Double(master.getCenterX() - 25, master.getCenterY() - 75, 50, 150);
double deltaX = -master.getCenterX();
double deltaY = -master.getCenterY();
double aWidth = master.getWidth();
double aHeight = master.getHeight();
double ratio = aWidth / aHeight;
g2.setStroke(new BasicStroke(3.0f));
g2.setColor(Color.red);
g2.draw(master);
g2.fill(new Ellipse2D.Double(95, 95, 10, 10));
g2.setColor(Color.green);
g2.draw(slave);
AffineTransform[] transforms;
if (combineTransforms) {
transforms = new AffineTransform[]{
AffineTransform.getTranslateInstance(-master.getCenterX(), -master.getCenterY()),
AffineTransform.getRotateInstance(-Math.PI / 6.000000),
AffineTransform.getTranslateInstance(master.getCenterX(), master.getCenterY())
};
} else {
transforms = new AffineTransform[]{AffineTransform.getRotateInstance(-Math.PI / 6.000000, master.getCenterX(), master.getCenterY())};
}
Color[] farben = new Color[]{Color.BLUE, Color.RED, Color.ORANGE, Color.PINK, Color.MAGENTA, Color.CYAN};
AffineTransform base = new AffineTransform();
for (int i = 0; i < 2; i++) {
g2.setColor(farben[i]);
if (modifyG2) {
if (combineTransforms) {
g2.translate(-deltaX, -deltaY);
g2.rotate(-Math.PI / 6.000000);
g2.translate(deltaX, deltaY);
} else {
g2.rotate(-Math.PI / 6.000000, deltaX, deltaY);
}
} else {
for (AffineTransform at : transforms) {
base.concatenate(at);
}
g2.setTransform(base);
}
g2.draw(slave);
}
g2.setTransform(oldAT);
}
}