Как Affine Transform действительно работает в Java? - PullRequest
5 голосов
/ 15 апреля 2011

Я использовал Affine Transform, чтобы вращать строку в своем Java-проекте, и я еще не опытный программист, поэтому мне потребовалось много времени, чтобы выполнить, казалось бы, маленькую задачу. *

Теперь я наконец-то заставил его работать более или менее так, как я надеялся, за исключением того, что это не так точно, как я хочу ... пока.

Поскольку потребовалось много проб и ошибок и прочтение описания аффинного преобразования, я все еще не совсем уверен, что он на самом деле делает. В настоящий момент я знаю, что я беру строку и определяю центр строки (или точку, которую я хочу вращать), но откуда в это вступают матрицы? (Видимо, я не знаю, что хе-хе)

Может ли кто-нибудь попытаться объяснить мне, как работает аффинное преобразование, другими словами, чем документ Java? Может быть, это поможет мне настроить мою реализацию, а также, я просто хотел бы знать:)

Заранее спасибо.

Ответы [ 5 ]

5 голосов
/ 15 апреля 2011

Чтобы понять, что такое аффинное преобразование и как оно работает, см. Википедию статья .

В общем, это линейное преобразование (например, масштабирование или отражение), которое может быть реализовано в виде умножения на конкретную матрицу, а затем с последующим переводом (перемещением), который выполняется путем добавления вектора. Таким образом, чтобы вычислить для каждого пикселя [x, y] его новое местоположение, вам нужно умножить его на конкретную матрицу (выполнить линейное преобразование), а затем добавить, а затем добавить конкретный вектор (выполнить перевод).

4 голосов
/ 15 апреля 2011

В дополнение к другим ответам, более высокий уровень просмотра:

  • Точки на экране имеют координаты ax и yy, то есть могут быть записаны как вектор (x, y).Можно представить, что более сложные геометрические объекты описываются набором точек.

  • Векторы (точка) можно умножить на матрицу, а в результате получается другой вектор (точка).

  • Существуют специальные (т. Е. Умно построенные) матрицы, которые при умножении на вектор приводят к тому, что результирующий вектор эквивалентен повороту, масштабированию, наклону или небольшому обману переводаточка ввода.

Вот и все, что нужно сделать.У этого подхода есть еще несколько причудливых особенностей:

  • Если вы умножите 2 матрицы, вы снова получите матрицу (по крайней мере, в этом случае; остановите придирки ;-)).
  • Если вы умножите 2 матрицы, которые эквивалентны 2 геометрическим преобразованиям, полученная матрица будет эквивалентна выполнению 2 геометрических преобразований одно за другим (порядок имеет значение между прочим).
  • Это означает, что вы можете закодировать произвольную цепочку этих геометрических преобразований в одну матрицу.И вы можете создать эту матрицу, умножив отдельные матрицы.
  • Кстати, это также работает в 3D.

Для получения более подробной информации см. Другие ответы.

2 голосов
/ 12 февраля 2012

Вот чисто математическое видео руководство, как спроектировать матрицу преобразования для ваших нужд http://www.khanacademy.org/video/linear-transformation-examples--scaling-and-reflections?topic=linear-algebra

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

2 голосов
/ 15 апреля 2011

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

  1. переместите точку вращения (x, y) в начало пространства, применив translate(-x,-y).
  2. сделать вращение rotate(angle) (возможно, здесь также будет выполнено масштабирование)
  3. переместить все обратно в исходную точку на translate(x,y).

Помните, что вы должны применять эти шаги в обратном порядке (см. Ответ trashgod).

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

Rectangle2D r = g.getFontMetrics().getStringBounds(text, g);
g.translate(final_x, final_y);
g.rotate(-angle);
g.translate(-r.getCenterX(), -r.getCenterY());
g.drawString(text, 0, 0);

или альтернативно

Rectangle2D r = g.getFontMetrics().getStringBounds(text, g);
AffineTransform trans = AffineTransform.getTranslateInstance(final_x, final_y);
trans.concatenate(AffineTransform.getRotateInstance(-angle));
trans.concatenate(AffineTransform.getTranslateInstance(-r.getCenterX(), -r.getCenterY()));
g.setTransform(trans);
g.drawString(text, 0, 0);
2 голосов
/ 15 апреля 2011

На практике я нашел две вещи полезными для понимания AffineTransform:

  1. Вы можете преобразовать либо графический контекст, Graphics2D, либо любой класс, который реализует интерфейс Shape, как обсуждено здесь .

  2. Связанные преобразования имеют видимый последний-указанный-первый-примененный порядок, также упоминается здесь .

...