Метод объединения нескольких аффинных преобразований, как если бы каждое из них было указано в не преобразованном пространстве - PullRequest
3 голосов
/ 28 апреля 2011

Я ищу способ комбинировать аффинные преобразования таким образом, чтобы эффект был эквивалентен использованию каждого преобразования для последовательного манипулирования формой.Проблема в том, что если я просто объединяю преобразования, то эффект каждого последующего преобразования интерпретируется в координатном пространстве существующего преобразования.

Например, рассмотрим квадрат вокруг начала координат (-50, -50, 100,100).Я хочу повернуть его, а затем перевести вниз на 100 пикселей.Если я возьму преобразование и поверну, а затем переведу, перевод интерпретируется в повернутых координатах.Вместо этого, если я преобразую саму форму, чтобы повернуть ее, а затем снова преобразовать эту форму, чтобы перевести ее, оба перевода интерпретируются в «нормальной» непереведенной плоскости, и это дает мне то, что я хочу.

Проблема в том, что для того, что я делаю, может иметь место много преобразований, каждое из которых необходимо интерпретировать в нормальной координатной плоскости, но я не хочу хранить стек преобразований и не могу просто продолжать манипулировать формой.потому что мне нужно в любое время быть в состоянии создать окончательную преобразованную форму из исходной начальной формы.

Example: normal concatenation on the left, successive transforms on the right

Я знаю, что для этого простого примера, если бы я сделалпереводить до поворота я получил бы тот же результат, но это не имеет смысла.Я имею дело с произвольным набором последовательных преобразований масштаба, перевода и поворота, поэтому простое размещение их в определенном порядке не обрезает его.

У меня есть предположение, что должен быть способ объединенияпреобразования таким образом, что вы изменяете новое преобразование перед его конкатенацией, исправляя существующее преобразование, так что в результате получается, что новое преобразование применено так, как если бы оно ссылалось на не преобразованную координатную плоскость.Например, если вы переводите с помощью (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-библиотека - это все, что здесь уместно.)

Ответы [ 2 ]

1 голос
/ 28 апреля 2011

Я предлагаю вам отслеживать некоторые абсолютные значения, а затем выполнять как можно меньше преобразований.

Например, сохранить матрицу перевода и угол поворота вокруг начала координат.

int translate[2];
int rotate;

Теперь предположим, что вы хотите повернуть вокруг его центра, затем перевести объект куда-нибудь, а затем повернуть его снова под его центром.Потому что с аффинными преобразованиями матрица вращения не является коммутативной, поэтому, если вы примените вращение, перемещение, вращение, вы получите неправильный результат.

Но вы можете просто сложить угол поворота первого и третьего вращенияи примените один поворот, а затем перевод.

Надеюсь, что будет ясно.

0 голосов
/ 28 апреля 2011

когда вы вращаете объект, вы обычно вращаетесь вокруг определенной точки. Похоже, вы просто вращаетесь вокруг (0,0), что обычно не то, что вы хотите.

Для поворота вокруг определенной точки (x, y),

  • перевести точку в 0 (-x, -y),
  • затем поверните,
  • затем переведите обратно (x, y).

    публичная статическая AffineTransform getRotateInstance (двойная тета, двойной якорь, двойная якорь)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...