Как на самом деле работает Affine Transform в Java?

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

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

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

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

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


person Simon Langhoff    schedule 14.04.2011    source источник
comment
Это больше математический вопрос, чем программирование. Посетите страницу Википедии об этом: en.wikipedia.org/wiki/Affine_transformation Не то, чтобы это было будет легче понять, чем JavaDoc. :) К сожалению, это всего лишь одна из тех вещей, которые вы должны пройти через грубое обучение, ИМХО.   -  person brindy    schedule 15.04.2011


Ответы (5)


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

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

person Michał Šrajer    schedule 14.04.2011

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

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

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

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

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

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

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

person Carsten    schedule 15.04.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);
person Howard    schedule 15.04.2011

С практической точки зрения я нашел две вещи, полезные для понимания AffineTransform:

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

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

person trashgod    schedule 14.04.2011

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

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

person belamoor    schedule 12.02.2012