Как сделать композицию афинных преобразований
К афинным преобразованиям относятся следующие преобразования- сжатие/растяжение(масштабирование), поворот, параллельный перенос
и сдвиг. Более подробно о каждом из этих преобразований можно почитать
здесь.
Рассмотрим ситуацию, когда нам нужно одновременно выполнить 2 преобразования. Например, сжатие и поворот. Однако если мы попробуем
выполнить эти преобразования в одном эксземпляре класса AffineTransform, то выполнится только последнее преобразование.
Например в следующем примере будет только поворот на 45 градусов:
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
AffineTransform at = new AffineTransform();
at.setToScale(2, 3);
at.setToRotation(Math.PI/4, 50, 50);
g2d.setTransform(at);
g2d.drawRect(30, 30, 60, 90);
}
Чтобы выполнить одновременно сжатие и поворот нужно использовать метод
concatenate(AffineTransform at) класса AffineTransform, который
позволяет делать композицию преобразований.
Тогда предыдущий пример нужно переписать в следующем виде:
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
AffineTransform atScale = new AffineTransform();
AffineTransform atRotate = new AffineTransform();
atScale.setToScale(0.4, 0.5);
atRotate.setToRotation(Math.PI/4, 50, 50);
atScale.concatenate(atRotate);
g2d.setTransform(at);
g2d.drawRect(30, 30, 60, 90);
}
Следует обратить внимание на порядок выполнения преобразований ввиду некоммутативности умножения матриц: сначала нужно сделать поворот, а потом сжатие.
Иначе при сжатии координаты центра вращения для 2го преобразования будут изменены и вращение будет происходить относительно уже другой точки.