Класс AffineTransform описывает функцию двумерного аффинного преобразования, которая представляет собой линейное преобразование двухмерных координат в двумерные координаты, сохраняя «прямолинейность» двухмерной графики (Перевод: прямолинейность, то есть прямая линия после трансформации) Это по-прежнему прямая линия без изгиба, а дуга по-прежнему дуга) и «параллельность» (Аннотация: параллельность, на самом деле означает сохранение неизменными относительных позиционных отношений между двумерными фигурами, параллельные линии по-прежнему остаются параллельными линиями, а углы пересечения пересекающихся прямых линий остаются неизменными. Комплексные переменные изучаются на втором курсе , « Помните «Конформное преобразование / Конформное преобразование», математика — король!). Аффинное преобразование может быть достигнуто посредством комбинации ряда атомарных преобразований, включая: перемещение, масштабирование, переворот, вращение и сдвиг.
Этот тип преобразования может быть представлен матрицей 3×3, последняя строка которой равна (0, 0, 1). Эта матрица преобразования преобразует исходные координаты (x, y) в новые координаты (x', y'). Здесь исходные координаты и новые координаты рассматриваются как трехмерный вектор-столбец последней строки (1). Исходный вектор-столбец преобразуется умножением слева. Матрица получает новые векторы-столбцы:
[x'] [m00 m01 m02] [x] [m00*x+m01*y+m02] [y'] = [m10 m11 m12] [y] = [m10*x+m11*y+m12] [1 ] [ 0 0 1 ] [1] [ 1 ]
Несколько типичных аффинных преобразований:
публичный статический AffineTransform getTranslateInstance (double tx, double ty)
Трансформация перевода: переместите каждую точку в (x+tx, y+ty), матрица преобразования:
[ 1 0 передача ] [ 0 1 ти ] [ 0 0 1 ]
(Аннотация: Трансляционное преобразование — это своего рода «трансформация твердого тела». Любой, кто изучал физику в средней школе, знает, что такое «твердое тело». Это идеальный объект, который не будет деформироваться. Конечно, перевод не изменится. двумерная графика. Точно так же «преобразование вращения» ниже также является преобразованием твердого тела, а «масштабирование» и «сквозное разрезание» изменят форму графики.)
общедоступный статический AffineTransform getScaleInstance (double sx, double sy)
Преобразование масштабирования увеличивает (уменьшает) абсциссу каждой точки в sx раз и увеличивает (уменьшает) ординату в sy раз. Матрица преобразования:
[ сх 0 0 ] [ 0 си 0 ] [ 0 0 1 ]
public static AffineTransform getShearInstance (двойной shx, двойной застенчивый)
Сдвиговое преобразование, матрица преобразования:
[ 1 шх 0 ] [ застенчивый 1 0 ] [ 0 0 1 ]
Эквивалент комбинации поперечного и продольного сдвига.
[ 1 0 0 ][ 1 shx 0 ] [ застенчивый 1 0 ][ 0 1 0 ] [ 0 0 1 ][ 0 0 1 ]
(Примечание к переводу: «Сдвиговую трансформацию» еще называют «неправильной трансформацией», что относится к свойствам, аналогичным четырехсторонней нестабильности. Вы когда-нибудь видели железные раздвижные двери в небольших магазинах на улице? Представьте себе железные прутья наверху. Процесс ромба вытягивание – процесс «неправильного разрезания»).
общедоступный статический AffineTransform getRotateInstance (двойная тета)
Преобразование вращения: целевой график вращает тета-радианы по часовой стрелке вокруг начала координат, матрица преобразования:
[ cos(тета) -sin(тета) 0 ] [ грех(тета) cos(тета) 0 ] [ 0 0 1 ]
public static AffineTransform getRotateInstance (двойная тета, двойной x, двойной y)
Преобразование вращения: целевое изображение поворачивается по часовой стрелке на тета-радианы с осью (x, y), а матрица преобразования имеет следующий вид:
[ cos(тета) -sin(тета) xx*cos+y*sin] [ грех(тета) cos(тета) yx*sin-y*cos ] [ 0 0 1 ]
Это эквивалентно соединению двух преобразований перемещения и одного преобразования вращения начала координат:
[1 0 -x][cos(тета) -sin(тета) 0][1 0 x] [0 1 -y][sin(тета) cos(тета) 0][0 1 y] [0 0 1 ] [0 0 1][0 0 1]
В геометрии векторное пространство подвергается линейному преобразованию, за которым следует сдвиг. Этот процесс называется аффинным преобразованием или радиальным отображением.
Это можно выразить просто как: y = Ax + b, где буква в нижнем индексе представляет вектор, а жирная буква A представляет матрицу.
Неважно, если вы пока не можете это понять (я тоже этого не понимаю^_^#), неважно, мы здесь используем только несколько особых случаев: перемещение и вращение. трансформация.
Как обычно, опубликуем весь код ниже:
импорт java.applet.Applet;импорт java.awt.BorderLayout;импорт java.awt.Checkbox;импорт java.awt.CheckboxGroup;импорт java.awt.Color;импорт java.awt.Graphics;импорт java.awt.Graphics2D;импорт java.awt.Panel;импорт java.awt.event.ItemEvent;импорт java.awt.event.ItemListener; импорт java.awt.geom.AffineTransform; импорт java.awt.geom.Rectangle2D; импорт java.util.Random; общедоступный класс AffineTest расширяет апплет, реализует ItemListener {частный Rectangle2D rect; частный Флажок RotateFirst; Флажок переводаFirst; public void init() { setLayout(new BorderLayout()); CheckboxGroup cbg = new CheckboxGroup (); Panel p = new Panel (); RotateFirst = new Checkbox («поворот, перевод», cbg, true); («перевести, повернуть», cbg, false); BorderLayout.SOUTH); rect = new Rectangle2D.Float(-0.5f, -0.5f, 1.0f, 1.0f); } public void Paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; Final AffineTransform идентификация = новый AffineTransform (); логическое значение Rotate = RotateFirst.getState(); Random r = новый Random(); oneRadian = Math.toRadians(1.0); for(double радианы = 0,0; радианы < 2,0*Math.PI ; радианы += oneRadian) { g2d.setTransform(identify); if(rotate) { g2d.translate(100, 100) ; g2d.rotate(радианы); } else { g2d.rotate(радианы); g2d.translate(100, 100); } g2d.scale(100, 100); g2d.setColor(new Color(r.nextInt())); g2d.fill(rect); } } @Override public void itemStateChanged(ItemEvent); arg0) { // TODO Автоматически сгенерированная заглушка метода repaint() }}import; java.applet.Applet;импорт java.awt.BorderLayout;импорт java.awt.Checkbox;импорт java.awt.CheckboxGroup;импорт java.awt.Color;импорт java.awt.Graphics;импорт java.awt.Graphics2D;импорт Java .awt.Panel;импорт java.awt.event.ItemEvent;импорт java.awt.event.ItemListener; импорт java.awt.geom.AffineTransform; импорт java.awt.geom.Rectangle2D; импорт java.util.Random; общедоступный класс AffineTest расширяет апплет, реализует ItemListener {частный Rectangle2D rect; частный Флажок RotateFirst; Флажок переводаFirst; public void init() { setLayout(new BorderLayout()); CheckboxGroup cbg = new CheckboxGroup (); Panel p = new Panel (); RotateFirst = new Checkbox («поворот, перевод», cbg, true); («перевести, повернуть», cbg, false); BorderLayout.SOUTH); rect = new Rectangle2D.Float(-0.5f, -0.5f, 1.0f, 1.0f); } public void Paint(Graphics g) { Graphics2D g2d = (Graphics2D)g; Final AffineTransform идентификация = новый AffineTransform (); логическое значение Rotate = RotateFirst.getState(); Random r = новый Random(); oneRadian = Math.toRadians(1.0); for(double радианы = 0,0; радианы < 2,0*Math.PI ; радианы += oneRadian) { g2d.setTransform(identify); if(rotate) { g2d.translate(100, 100) ; g2d.rotate(радианы); } else { g2d.rotate(радианы); g2d.translate(100, 100); } g2d.scale(100, 100); g2d.setColor(new Color(r.nextInt())); g2d.fill(rect); } } @Override public void itemStateChanged(ItemEvent); arg0) { // TODO Автоматически сгенерированная заглушка метода repaint() }};
Из сравнения видно, что порядок аффинного преобразования нельзя случайно поменять.