一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - 初步解析Java中AffineTransform類的使用

初步解析Java中AffineTransform類的使用

2020-01-10 16:16computingbear JAVA教程

這篇文章主要介紹了Java中AffineTransform類的使用,AffineTransform類經(jīng)常被用來處理圖片,需要的朋友可以參考下

AffineTransform類描述了一種二維仿射變換的功能,它是一種二維坐標(biāo)到二維坐標(biāo)之間的線性變換,保持二維圖形的“平直性”(譯注:straightness,即變換后直線還是直線不會打彎,圓弧還是圓弧)和“平行性”(譯注:parallelness,其實是指保二維圖形間的相對位置關(guān)系不變,平行線還是平行線,相交直線的交角不變。大二學(xué)過的復(fù)變,“保形變換/保角變換”都還記得吧,數(shù)學(xué)就是王道啊!)。仿射變換可以通過一系列的原子變換的復(fù)合來實現(xiàn),包括:平移(Translation)、縮放(Scale)、翻轉(zhuǎn)(Flip)、旋轉(zhuǎn)(Rotation)和剪切(Shear)。

此類變換可以用一個3×3的矩陣來表示,其最后一行為(0, 0, 1)。該變換矩陣將原坐標(biāo)(x, y)變換為新坐標(biāo)(x', y'),這里原坐標(biāo)和新坐標(biāo)皆視為最末一行為(1)的三維列向量,原列向量左乘變換矩陣得到新的列向量:

?
1
2
3
[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 ]

 


幾種典型的仿射變換:

?
1
public static AffineTransform getTranslateInstance(double tx, double ty)

 

平移變換,將每一點移動到(x+tx, y+ty),變換矩陣為:

?
1
2
3
[ 1 0 tx ]
[ 0 1 ty ]
[ 0 0 1 ]


(譯注:平移變換是一種“剛體變換”,rigid-body transformation,中學(xué)學(xué)過的物理,都知道啥叫“剛體”吧,就是不會產(chǎn)生形變的理想物體,平移當(dāng)然不會改變二維圖形的形狀。同理,下面的“旋轉(zhuǎn)變換”也是剛體變換,而“縮放”、“錯切”都是會改變圖形形狀的。)

?
1
public static AffineTransform getScaleInstance(double sx, double sy)

 

縮放變換,將每一點的橫坐標(biāo)放大(縮小)至sx倍,縱坐標(biāo)放大(縮小)至sy倍,變換矩陣為:

?
1
2
3
[ sx 0 0 ]
[ 0 sy 0 ]
[ 0 0 1 ]
?
1
public static AffineTransform getShearInstance(double shx, double shy)

 

剪切變換,變換矩陣為:

?
1
2
3
[ 1 shx 0 ]
[ shy 1 0 ]
[ 0 0 1 ]

相當(dāng)于一個橫向剪切與一個縱向剪切的復(fù)合

?
1
2
3
[ 1 0 0 ][ 1 shx 0 ]
[ shy 1 0 ][ 0 1 0 ]
[ 0 0 1 ][ 0 0 1 ]


(譯注:“剪切變換”又稱“錯切變換”,指的是類似于四邊形不穩(wěn)定性那種性質(zhì),街邊小商店那種鐵拉門都見過吧?想象一下上面鐵條構(gòu)成的菱形拉動的過程,那就是“錯切”的過程。)

?
1
public static AffineTransform getRotateInstance(double theta)

 

旋轉(zhuǎn)變換,目標(biāo)圖形圍繞原點順時針旋轉(zhuǎn)theta弧度,變換矩陣為:

?
1
2
3
4
[ cos(theta) -sin(theta) 0 ]
 
[ sin(theta) cos(theta) 0 ]
[ 0 0 1 ]

 

?
1
public static AffineTransform getRotateInstance(double theta, double x, double y)

 

旋轉(zhuǎn)變換,目標(biāo)圖形以(x, y)為軸心順時針旋轉(zhuǎn)theta弧度,變換矩陣為:

?
1
2
3
[ cos(theta) -sin(theta) x-x*cos+y*sin]
[ sin(theta) cos(theta) y-x*sin-y*cos ]
[ 0 0 1 ]


相當(dāng)于兩次平移變換與一次原點旋轉(zhuǎn)變換的復(fù)合:

?
1
2
3
[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]

幾何中,一個向量空間進行一次線性變換并接上一個平移,這么一個過程就稱為仿射變換或放射映射。

可以簡單地表示為:y = Ax + b ,其中有下標(biāo)的字母表示向量,而粗體的字母A表示一個矩陣。

如果暫時無法理解也沒有關(guān)系(我也沒理解 ^_^#),沒關(guān)系,我們這里僅使用了它的幾個特例:平移和旋轉(zhuǎn)變換。

按照慣例,下面先把整個代碼貼出來:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Panel;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.Random;
 
 
public class AffineTest extends Applet implements ItemListener{
 
 private Rectangle2D rect;
 
 private Checkbox rotateFirst;
 private Checkbox translateFirst;
 
 public void init()
 {
 setLayout(new BorderLayout());
 CheckboxGroup cbg = new CheckboxGroup();
 Panel p = new Panel();
 rotateFirst = new Checkbox("rotate, translate", cbg, true);
 rotateFirst.addItemListener(this);
 p.add(rotateFirst);
 translateFirst = new Checkbox("translate, rotate", cbg, false);
 translateFirst.addItemListener(this);
 p.add(translateFirst);
 add(p, 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 identify = new AffineTransform();
 boolean rotate = rotateFirst.getState();
 Random r = new Random();
 final double oneRadian = Math.toRadians(1.0);
 for(double radians = 0.0; radians < 2.0*Math.PI ; radians += oneRadian)
 {
  g2d.setTransform(identify);
  if(rotate)
  {
  g2d.translate(100, 100);
  g2d.rotate(radians);
  }
  else
  {
  g2d.rotate(radians);
  g2d.translate(100, 100);
  }
  g2d.scale(100, 100);
  g2d.setColor(new Color(r.nextInt()));
  g2d.fill(rect);
 }
 }
 
 @Override
 public void itemStateChanged(ItemEvent arg0) {
 // TODO Auto-generated method stub
 repaint();
 }
 
}
 
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Panel;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.Random;
 
 
public class AffineTest extends Applet implements ItemListener{
 
 private Rectangle2D rect;
 
 private Checkbox rotateFirst;
 private Checkbox translateFirst;
 
 public void init()
 {
 setLayout(new BorderLayout());
 CheckboxGroup cbg = new CheckboxGroup();
 Panel p = new Panel();
 rotateFirst = new Checkbox("rotate, translate", cbg, true);
 rotateFirst.addItemListener(this);
 p.add(rotateFirst);
 translateFirst = new Checkbox("translate, rotate", cbg, false);
 translateFirst.addItemListener(this);
 p.add(translateFirst);
 add(p, 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 identify = new AffineTransform();
 boolean rotate = rotateFirst.getState();
 Random r = new Random();
 final double oneRadian = Math.toRadians(1.0);
 for(double radians = 0.0; radians < 2.0*Math.PI ; radians += oneRadian)
 {
  g2d.setTransform(identify);
  if(rotate)
  {
  g2d.translate(100, 100);
  g2d.rotate(radians);
  }
  else
  {
  g2d.rotate(radians);
  g2d.translate(100, 100);
  }
  g2d.scale(100, 100);
  g2d.setColor(new Color(r.nextInt()));
  g2d.fill(rect);
 }
 }
 
 @Override
 public void itemStateChanged(ItemEvent arg0) {
 // TODO Auto-generated method stub
 repaint();
 }
 
}

初步解析Java中AffineTransform類的使用

初步解析Java中AffineTransform類的使用
對比可知,仿射變換的順序是不能隨便交換的。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 从后面撕开老师的丝袜动态图 | 香蕉国产成版人视频在线观看 | 天天久久影视色香综合网 | 欧美一区二区三区四区在线观看 | 国产一区二区三区毛片 | 日本在线小视频 | 亚洲午夜精品久久久久久成年 | 日韩欧美亚洲一区二区综合 | 亚洲欧美国产精品完整版 | 精品视频在线免费看 | 第一福利在线导航 | 国产成人咱精品视频免费网站 | 沟厕okn系列在线播放 | 97超pen个人视频公开视频视 | 国产亚洲精品日韩香蕉网 | 国产中文字幕 | www.俺去| 亚洲va国产日韩欧美精品色婷婷 | 性一交一无一伦一精一品 | 手机在线观看伦理片 | ass日本乱妇ass | 加勒比一本大道在线 | 婷婷影院在线观看 | 日韩乱淫| 九九热在线视频 | 欧美日韩视频在线一区二区 | 校花在公车上被内射好舒服 | 男同激情视频 | 色综合色狠狠天天综合色 | 亚洲卡一卡2卡三卡4麻豆 | dasd-698黑人在线播放 | 欧美老骚 | 亚洲欧美一区二区三区在线观看 | 500第一精品| 国产精品久久免费观看 | 成人猫咪maomiav永久网址 | 万域之王动漫在线观看全集免费播放 | 日本在线一区二区 | 图片一区 | 亚洲黄色片免费看 | 欧美日韩一区二区中文字幕视频 |