La clase AffineTransform describe una función de transformación afín bidimensional, que es una transformación lineal de coordenadas bidimensionales a coordenadas bidimensionales, manteniendo la "rectitud" de los gráficos bidimensionales (Traducción: rectitud, es decir, la línea recta después de la transformación) Sigue siendo una línea recta sin doblarse, y un arco sigue siendo arco) y "paralelismo" (Anotación: paralelismo, en realidad se refiere a mantener sin cambios la relación posicional relativa entre figuras bidimensionales, las líneas paralelas siguen siendo líneas paralelas y los ángulos de intersección de las líneas rectas que se cruzan permanecen sin cambios. Variables complejas aprendidas en el segundo año , " Recuerde "Transformación conforme/Transformación conforme", ¡las matemáticas son el rey!). La transformación afín se puede lograr mediante una combinación de una serie de transformaciones atómicas, que incluyen: traslación, escala, inversión, rotación y corte.
Este tipo de transformación se puede representar mediante una matriz de 3×3, cuya última fila es (0, 0, 1). Esta matriz de transformación transforma las coordenadas originales (x, y) en las nuevas coordenadas (x', y'. Aquí, las coordenadas originales y las nuevas coordenadas se consideran como el vector columna tridimensional de la última fila (1). El vector columna original se transforma mediante multiplicación por la izquierda. La matriz obtiene nuevos vectores columna:
[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 ]
Varias transformaciones afines típicas:
público estático AffineTransform getTranslateInstance (doble tx, doble ty)
Transformación de traducción, mueva cada punto a (x + tx, y + ty), la matriz de transformación es:
[ 1 0 tx ] [ 0 1 ty ] [ 0 0 1 ]
(Anotación: La transformación de traducción es una especie de "transformación de cuerpo rígido". Cualquiera que haya estudiado física en la escuela secundaria sabe qué es un "cuerpo rígido". Es un objeto ideal que no se deformará. Por supuesto, la traducción no cambiará. los gráficos bidimensionales de la misma manera, la "transformación de rotación" a continuación también es una transformación de cuerpo rígido, y el "escalado" y el "corte transversal" cambiarán la forma del gráfico).
público estático AffineTransform getScaleInstance (doble sx, doble sy)
La transformación de escala aumenta (reduce) la abscisa de cada punto a seis veces y aumenta (reduce) la ordenada a sy veces. La matriz de transformación es:
[ sx 0 0 ] [ 0 sy 0 ] [ 0 0 1 ]
público estático AffineTransform getShearInstance (doble shx, doble tímido)
Transformación de corte, la matriz de transformación es:
[ 1 shx 0 ] [ tímido 1 0 ] [ 0 0 1 ]
Equivalente a una combinación de corte transversal y corte longitudinal
[ 1 0 0 ][ 1 shx 0 ] [ tímido 1 0 ][ 0 1 0 ] [ 0 0 1 ][ 0 0 1 ]
(Nota de traducción: la "transformación de corte" también se llama "transformación de corte incorrecto", que se refiere a propiedades similares a la inestabilidad del cuadrilátero. ¿Alguna vez has visto las puertas correderas de hierro en las pequeñas tiendas de la calle? Imagínate las barras de hierro de arriba. El proceso del rombo tirar es el proceso de "cortar mal").
AffineTransform estático público getRotateInstance (doble theta)
Transformación de rotación, el gráfico de destino gira theta radianes en el sentido de las agujas del reloj alrededor del origen, la matriz de transformación es:
[ cos(theta) -sin(theta) 0 ] [ sin(theta) cos(theta) 0 ] [ 0 0 1 ]
público estático AffineTransform getRotateInstance (doble theta, doble x, doble y)
Transformación de rotación, el gráfico de destino se gira en el sentido de las agujas del reloj en theta radianes con (x, y) como eje, y la matriz de transformación es:
[ cos(theta) -sin(theta) xx*cos+y*sin] [ sin(theta) cos(theta) yx*sin-y*cos ] [ 0 0 1 ]
Es equivalente a la combinación de dos transformaciones de traslación y una transformación de rotación de origen:
[1 0 -x][cos(theta) -sin(theta) 0][1 0 x] [0 1 -y][sin(theta) cos(theta) 0][0 1 y] [0 0 1 ] [0 0 1][0 0 1]
En geometría, un espacio vectorial sufre una transformación lineal seguida de una traslación. Este proceso se llama transformación afín o mapeo radial.
Se puede expresar simplemente como: y = Ax + b, donde la letra subíndice representa un vector y la letra A en negrita representa una matriz.
No importa si no puedes entenderlo por el momento (yo tampoco lo entiendo ^_^#), no importa, aquí solo usamos algunos casos especiales: traducción y rotación. transformación.
Como de costumbre, publiquemos el código completo a continuación:
importar java.applet.Applet;importar java.awt.BorderLayout;importar java.awt.Checkbox;importar java.awt.CheckboxGroup;importar java.awt.Color;importar java.awt.Graphics;importar java.awt.Graphics2D;importar java.awt.Panel;importar java.awt.event.ItemEvent;importar java.awt.event.ItemListener;importar java.awt.geom.AffineTransform;importar java.awt.geom.Rectangle2D;importar java.util.Random;la clase pública AffineTest extiende Applet implementa ItemListener{ privado Rectángulo2D privado Casilla de verificación rotarPrimero; Casilla de verificación traducirPrimero; public void init() { setLayout(new BorderLayout()); CheckboxGroup cbg = nuevo CheckboxGroup(); Panel p = nuevo Panel(); rotarPrimero = nueva casilla de verificación("rotar, traducir", cbg, verdadero); rotarPrimero.addItemListener(this); ("traducir, rotar", cbg, false); traducirFirst.addItemListener(this); p.add(translateFirst); BorderLayout.SOUTH); rect = new Triangle2D.Float(-0.5f, -0.5f, 1.0f, 1.0f); } pintura vacía pública (Gráficos g) { Graphics2D g2d = (Graphics2D)g; (); rotación booleana = rotarPrimero.getState(); Aleatorio r = nuevo Aleatorio(); oneRadian = Math.toRadians(1.0); for(doble radianes = 0.0; radianes < 2.0*Math.PI; radianes += oneRadian) { g2d.setTransform(identify); if(rotate) { g2d.translate(100, 100) ; g2d.rotate(radianes); } else { g2d.rotate(radianes); g2d.translate(100, 100); } g2d.scale(100, 100); g2d.setColor(new Color(r.nextInt())); g2d.fill(rect); arg0) { // TODO Método generado automáticamente stub repaint() }}importar java.applet.Applet;importar java.awt.BorderLayout;importar java.awt.Checkbox;importar java.awt.CheckboxGroup;importar java.awt.Color;importar java.awt.Graphics;importar java.awt.Graphics2D;importar java .awt.Panel;importar java.awt.event.ItemEvent;importar java.awt.event.ItemListener;importar java.awt.geom.AffineTransform;importar java.awt.geom.Rectangle2D;importar java.util.Random;la clase pública AffineTest extiende Applet implementa ItemListener{ privado Rectángulo2D privado Casilla de verificación rotarPrimero; Casilla de verificación traducirPrimero; public void init() { setLayout(new BorderLayout()); CheckboxGroup cbg = nuevo CheckboxGroup(); Panel p = nuevo Panel(); rotarPrimero = nueva casilla de verificación("rotar, traducir", cbg, verdadero); rotarPrimero.addItemListener(this); ("traducir, rotar", cbg, false); traducirFirst.addItemListener(this); p.add(translateFirst); BorderLayout.SOUTH); rect = new Triangle2D.Float(-0.5f, -0.5f, 1.0f, 1.0f); } pintura vacía pública (Gráficos g) { Graphics2D g2d = (Graphics2D)g; (); rotación booleana = rotarPrimero.getState(); Aleatorio r = nuevo Aleatorio(); oneRadian = Math.toRadians(1.0); for(doble radianes = 0.0; radianes < 2.0*Math.PI; radianes += oneRadian) { g2d.setTransform(identify); if(rotate) { g2d.translate(100, 100) ; g2d.rotate(radianes); } else { g2d.rotate(radianes); g2d.translate(100, 100); } g2d.scale(100, 100); g2d.setColor(new Color(r.nextInt())); g2d.fill(rect); arg0) { // TODO Método generado automáticamente stub repaint();
En comparación, se puede ver que el orden de transformación afín no se puede intercambiar casualmente.