我正在寻找一种以这种方式组合仿射变换的方法,以便效果等同于使用每个变换来连续操纵形状。问题是如果我简单地连接变换,那么每个连续变换的效果都会在现有变换的坐标空间中解释。
例如,考虑原点周围的正方形(-50、-50、100,100)。我想旋转它,然后将它向下平移 100 像素。如果我进行变换并旋转然后平移,则平移将在旋转坐标中进行解释。相反,如果我变换形状本身以旋转它,然后再次变换该形状以翻译它,则两种翻译都在“正常”未翻译平面中解释,它给了我我想要的东西。
问题是,对于我正在做的事情,可能会发生许多变换,每个变换都需要在法线坐标平面中进行解释,但我不想存储一堆变换,也不能简单地继续操纵形状,因为我需要随时能够从原始起始形状创建最终的转换形状。
我知道,对于这个简单的示例,如果我在旋转之前进行翻译,我会得到相同的结果,但这没有抓住重点。我正在处理一组任意的连续缩放、平移和旋转变换,因此简单地将它们按特定顺序放置并不会减少它。
我有一种暗示,应该有一种方法来连接变换,以便在连接之前修改新变换,纠正现有变换,以便效果是新变换似乎已被应用,就好像它参考未转换的坐标平面。例如,如果您在上面的示例中转换为 (70.7, 70.7) 而不是 (0,100),则结果将变得等价。我只是似乎无法弄清楚数学是什么,通常要弄清楚如何改变新的变换,使其正常工作。
感谢阅读 - 希望这是有道理的。下面是创建屏幕截图的示例的来源:
public class TransformExample extends JPanel {
@Override
protected void paintComponent(Graphics _g) {
super.paintComponent(_g);
Graphics2D g = (Graphics2D) _g;
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.translate(150, 100); // translate so we can see method 1 clearly
paintConcatenate(g);
g.translate(200, 0); // translate again so we can see method 2 to the right of method 1
paintSuccessive(g);
}
private void paintConcatenate(Graphics2D g) {
AffineTransform tx = new AffineTransform();
Shape shape = new Rectangle(-50, -50, 100, 100);
// Draw the 3 steps, altering the transform each time
draw(g, shape, tx, Color.GRAY);
tx.rotate(Math.PI / 4);
draw(g, shape, tx, Color.GREEN);
tx.translate(70.7, 70.7);
draw(g, shape, tx, Color.PINK);
}
private void paintSuccessive(Graphics2D g) {
Shape shape = new Rectangle(-50, -50, 100, 100);
// Draw the 3 steps, altering the shape each time with a new transform
draw(g, shape, null, Color.GRAY);
shape = AffineTransform.getRotateInstance(Math.PI / 4).createTransformedShape(shape);
draw(g, shape, null, Color.GREEN);
shape = AffineTransform.getTranslateInstance(0, 100).createTransformedShape(shape);
draw(g, shape, null, Color.PINK);
}
private void draw(Graphics2D g, Shape shape, AffineTransform tx, Color color) {
if (tx != null) {
shape = tx.createTransformedShape(shape);
}
g.setColor(color);
g.fill(shape);
}
public static void main(String[] args) {
JFrame f = new JFrame("Transform Example");
f.setSize(500, 350);
f.setContentPane(new TransformExample());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
(我正在使用 Java2D,尽管我认为语言或 2d 库在这里并不是那么相关。)