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

服務(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類的使用
對比可知,仿射變換的順序是不能隨便交換的。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 精选国产AV精选一区二区三区 | 男人使劲躁女人小视频 | 精品淑女少妇AV久久免费 | 四虎国产精品视频免费看 | 天天摸天天碰色综合网 | 午夜香蕉成视频人网站高清版 | www射com| 国产男人天堂 | 午夜A级理论片左线播放 | 极品妖艳许清赵丽全文免费阅读 | 四虎永久在线精品免费影视 | 午夜爽喷水无码成人18禁三级 | 五月天精品在线 | 日本国产高清色www视频在线 | 免费网站看v片在线成人国产系列 | 黄网国产 | 婷婷草| 九九99香蕉在线视频美国毛片 | 国产亚洲sss在线观看 | 好男人资源免费播放 | 狠狠色婷婷 | 欧美日韩一级视频 | 好看华人华人经典play | 欧美亚洲桃花综合 | 2021麻豆剧果冻传媒入口永久 | 色噜噜亚洲男人的天堂www | 久久久久久久国产精品视频 | 成人在线视频播放 | 国产主播精品在线 | 国产色婷婷亚洲 | 欧美精品一二三区 | 天天舔天天操天天干 | 精品国产自在在线在线观看 | 国产激情视频网站 | 国产毛片一级aaaaa片 | 羞羞色男人的天堂伊人久久 | 国产精品视频第一区二区三区 | 爽好舒服宝贝添奶吻戏 | 视频国产91 | 日本b站一卡二不卡三卡四卡 | 亚洲不卡高清免v无码屋 |