最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

初步解析Java中AffineTransform類的使用

 更新時間:2015年10月16日 09:06:13   作者:computingbear  
這篇文章主要介紹了Java中AffineTransform類的使用,AffineTransform類經(jīng)常被用來處理圖片,需要的朋友可以參考下

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

此類變換可以用一個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 ] 


幾種典型的仿射變換:

public static AffineTransform getTranslateInstance(double tx, double ty) 


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

[ 1 0 tx ] 
[ 0 1 ty ] 
[ 0 0 1 ] 


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

public static AffineTransform getScaleInstance(double sx, double sy) 


縮放變換,將每一點的橫坐標放大(縮小)至sx倍,縱坐標放大(縮?。┲羢y倍,變換矩陣為:

[ sx 0 0 ] 
[ 0 sy 0 ] 
[ 0 0 1 ] 

public static AffineTransform getShearInstance(double shx, double shy) 

剪切變換,變換矩陣為:

[ 1 shx 0 ] 
[ shy 1 0 ] 
[ 0 0 1 ] 

相當于一個橫向剪切與一個縱向剪切的復合

[ 1 0 0 ][ 1 shx 0 ] 
[ shy 1 0 ][ 0 1 0 ] 
[ 0 0 1 ][ 0 0 1 ] 


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

public static AffineTransform getRotateInstance(double theta) 


旋轉變換,目標圖形圍繞原點順時針旋轉theta弧度,變換矩陣為:

[ cos(theta) -sin(theta) 0 ] 

[ sin(theta) cos(theta) 0 ] 
[ 0 0 1 ] 


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

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

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


相當于兩次平移變換與一次原點旋轉變換的復合:

[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 ,其中有下標的字母表示向量,而粗體的字母A表示一個矩陣。

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

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

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();
 }

}


對比可知,仿射變換的順序是不能隨便交換的。

相關文章

  • Spring?Boot自動配置的原理及@Conditional條件注解

    Spring?Boot自動配置的原理及@Conditional條件注解

    這篇文章主要介紹了Spring?Boot自動配置的原理及@Conditional條件注解,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,感興趣的朋友可以參考一下
    2022-07-07
  • 一文讀懂Spring中@Bean注解的核心作用

    一文讀懂Spring中@Bean注解的核心作用

    快速了解Spring框架中的@Bean注解?本文將帶你一鍵掌握其核心作用!只需一篇短文,揭示@Bean注解如何在Spring中定義bean實例,以及管理和裝配Bean的奧秘,閱讀指南,讓Spring開發(fā)更加得心應手!
    2024-01-01
  • 詳解maven中profiles使用實現(xiàn)

    詳解maven中profiles使用實現(xiàn)

    本文主要介紹了maven中profiles使用實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java實現(xiàn)學生管理系統(tǒng)

    Java實現(xiàn)學生管理系統(tǒng)

    這篇文章主要為大家詳細介紹了Java實現(xiàn)學生管理系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • CompletableFuture并行處理List分批數(shù)據(jù)demo

    CompletableFuture并行處理List分批數(shù)據(jù)demo

    這篇文章主要介紹了CompletableFuture并行處理List分批數(shù)據(jù)實現(xiàn)實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • Java基本數(shù)據(jù)類型存儲在JVM中的存儲位置介紹

    Java基本數(shù)據(jù)類型存儲在JVM中的存儲位置介紹

    這篇文章主要介紹了Java基本數(shù)據(jù)類型存儲在JVM中的存儲位置,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 超詳細介紹idea中java程序打jar包的兩種方式

    超詳細介紹idea中java程序打jar包的兩種方式

    這篇文章主要介紹了超詳細介紹idea中java程序打jar包的兩種方式一種是可直接執(zhí)行的runnable jar文件,另一種是包含多個主類,運行時需要指定主類全類名的jar包,感興趣的可以了解一下
    2020-07-07
  • 利用Java實現(xiàn)天氣預報播報功能

    利用Java實現(xiàn)天氣預報播報功能

    這篇文章主要為大家介紹了如何利用Java語言實現(xiàn)天氣預報播報功能,文中的示例代碼講解詳細,對我們學習Java有一定的幫助,需要的可以參考一下
    2022-06-06
  • Maven使用集成測試的示例代碼

    Maven使用集成測試的示例代碼

    本文介紹了在Maven項目中使用maven-failsafe-plugin插件進行集成測試,步驟包括添加測試依賴、編寫集成測試類、配置插件、運行測試以及查看和分析測試結果,感興趣的可以了解一下
    2024-11-11
  • Java設計實現(xiàn)一個針對各種類型的緩存

    Java設計實現(xiàn)一個針對各種類型的緩存

    這篇文章主要為大家詳細介紹了Java如何設計實現(xiàn)一個針對各種類型的緩存,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解一下
    2023-11-11

最新評論

田东县| 荥阳市| 宜昌市| 竹北市| 衡阳县| 黄浦区| 罗山县| 泰来县| 仁化县| 东乌珠穆沁旗| 漯河市| 邯郸县| 安义县| 雷山县| 乾安县| 资源县| 怀柔区| 石城县| 阜南县| 稻城县| 始兴县| 遂平县| 广元市| 武汉市| 黄浦区| 文水县| 安康市| 金平| 甘南县| 深州市| 陕西省| 修武县| 盐边县| 禹城市| 宜昌市| 右玉县| 汉源县| 汕头市| 阜平县| 九龙城区| 多伦县|