摘要:什么是仿射變換一組設(shè)備無關(guān)的坐標(biāo)被用來將所有的坐標(biāo)信息傳遞給對象。對象作為對象狀態(tài)的一部分。類代表一個(gè)的仿射變化,將一組的坐標(biāo)進(jìn)行線性映射到另一組保留了平行關(guān)系和豎直關(guān)系的坐標(biāo)中。
什么是仿射變換
一組設(shè)備無關(guān)的坐標(biāo)被用來將所有的坐標(biāo)信息傳遞給Graphics2D對象。AffineTransform對象作為Graphics2D對象狀態(tài)的一部分。該對象定義了如何將用戶空間的坐標(biāo)轉(zhuǎn)化為設(shè)備空間的設(shè)備相關(guān)的坐標(biāo)點(diǎn)。
AffineTransform類代表一個(gè)2D的仿射變化,將一組2D的坐標(biāo)進(jìn)行線性映射到另一組保留了平行關(guān)系和豎直關(guān)系的2D坐標(biāo)中。該轉(zhuǎn)化包括平移,縮放,翻轉(zhuǎn),旋轉(zhuǎn)和扭曲。根據(jù)AffineTransform定義的變化有兩個(gè)非常重要的屬性:
直線依然是直線
平行的線依然保持平行AffineTransform是限次那個(gè)轉(zhuǎn)化,所以可以通過矩陣的形式表示轉(zhuǎn)化,然以一個(gè)AffineTransform可以通過數(shù)學(xué)的形式轉(zhuǎn)化為一個(gè)包含六個(gè)數(shù)字的矩陣。
sx shx tx
shy sy ty
這里省略了矩陣的大括號。
不要方!不要擔(dān)心看不懂矩陣。你不需要了解矩陣運(yùn)算的一切。你只需要有些許的基礎(chǔ)知識(shí)即可。
事實(shí)上,你甚至不用擔(dān)心需要理解一般的矩陣運(yùn)算來完成接下來我將說明的簡單轉(zhuǎn)換,但是這些可以幫助你更好的理解它是如何運(yùn)作的。
矩陣?yán)锏姆柖即砩叮?/b>我將說明如何使用AffineTransform使圖片在展示于外設(shè)之前進(jìn)行下列轉(zhuǎn)換:
縮放
平移
扭曲
旋轉(zhuǎn)
在上面的矩陣中,sx和sy代表縮放的比例,tx和ty是實(shí)現(xiàn)平移的參數(shù)。shx和shy是實(shí)現(xiàn)扭曲的參數(shù)。
旋轉(zhuǎn)實(shí)際上是縮放和扭曲的組合,所以它可以由上面的參數(shù)組合完成操作。
如何使用這些參數(shù)?// ‘*’ 代表乘號 newX = sx*x + shx*y + tx newY = shy*x + sy*y + ty
假設(shè)在用戶空間中存在坐標(biāo)(x, y),這些參數(shù)將通過上面的公式計(jì)算出新的坐標(biāo),從而實(shí)現(xiàn)縮放,扭曲和平移。
我們后面會(huì)看到,如果表示剪切和平移的因子的值為零,那么將不執(zhí)行該類型的變換。如果縮放的值為1(默認(rèn)值),那么圖片不會(huì)進(jìn)行縮放。其它的任何值都會(huì)導(dǎo)致縮放,平移或扭曲的發(fā)生。
對于所有三種類型的變換,用于變換x坐標(biāo)的值與用于變換y坐標(biāo)的值無關(guān)。因此,例如,可以對x進(jìn)行大樹枝的平移,并在y中用進(jìn)行小數(shù)值平移。
在詳細(xì)描述執(zhí)行這些轉(zhuǎn)換之前,對每個(gè)轉(zhuǎn)換提供些許解釋可能會(huì)很有用。
縮放縮放可能是四種轉(zhuǎn)化中最好理解的一種。它是指如果一個(gè)點(diǎn)在用戶空間中的坐標(biāo)為(x,y),那么它在設(shè)備空間中的坐標(biāo)為(sx * x, sy * y )。乘數(shù)sx與sy可以為正數(shù)或是負(fù)數(shù)。
平移平移的目的是在設(shè)備空間中移動(dòng)坐標(biāo)系的原點(diǎn)。
比如,默認(rèn)的原點(diǎn)是組件左上角的點(diǎn)。假設(shè)組件是一個(gè)邊長四英寸的Frame,你可能希望原點(diǎn)位于框架的中心,而不是左上角。你可以通過將原點(diǎn)坐標(biāo)分別從水平和垂直方向平移兩英寸實(shí)現(xiàn)。
另一個(gè)使用平移的場景(與縮放同時(shí)使用)是翻轉(zhuǎn)垂直軸的默認(rèn)正方向,從而使y軸值的增加使得點(diǎn)向上移動(dòng)而不是默認(rèn)的向下移動(dòng)。
扭曲這是網(wǎng)上給的一個(gè)shearing的圖例,即將原圖以平行四邊形拉伸。
旋轉(zhuǎn)旋轉(zhuǎn)從視覺上很好理解。為了可視化旋轉(zhuǎn),在一張紙上畫一張照片。 使用一個(gè)釘子將其粘到公告板上。 然后圍繞大頭釘旋轉(zhuǎn)紙張。
在Java 2D中,旋轉(zhuǎn)是使用radians而不是degree的形式傳入?yún)?shù)。如果您不熟悉使用弧度度量來指定角度,請記住以下標(biāo)識(shí):
PI radians = 180 degrees
PI是在幾何類中學(xué)到的數(shù)值。它的值為3.14159...........。但是,你無須記住PI的數(shù)值,因?yàn)镸ATH類中包含了它的靜態(tài)值。你可以通過Math.PI獲得該值。
還有一個(gè)需要關(guān)注的是正角度的旋轉(zhuǎn)代表順時(shí)針旋轉(zhuǎn)。
簡單的程序我們來看看一些代碼,并且學(xué)習(xí)使用Java 2D實(shí)現(xiàn)縮放,平移,扭曲和旋轉(zhuǎn)。
可疊加但不可交換你會(huì)發(fā)現(xiàn)執(zhí)行兩個(gè)或是多個(gè)變化帶來的結(jié)果是累加的,但是不是可交換的。比如,執(zhí)行平移和旋轉(zhuǎn)并不一定等于先旋轉(zhuǎn)再平移得到的結(jié)果。
6個(gè)參數(shù)執(zhí)行相應(yīng)操作時(shí)對應(yīng)的矩陣參數(shù)如下:
默認(rèn) 1.0 0.0 0.0 0.0 1.0 0.0 添加縮放轉(zhuǎn)換 1.6666666666666667 0.0 0.0 0.0 1.6666666666666667 0.0 添加平移轉(zhuǎn)換 1.6666666666666667 0.0 30.0 0.0 1.6666666666666667 30.0 添加扭曲轉(zhuǎn)換 1.6666666666666667 0.08333333333333334 30.0 0.16666666666666669 1.666666666666666730.0 添加旋轉(zhuǎn)轉(zhuǎn)換 1.6508996608400615 -0.2434184299932779 79.32270275806317 0.4886147500940855 1.6021270803360292 -7.066823581936546完整代碼
import java.awt.geom.*; import java.awt.*; import java.awt.event.*; class Affine01{ publicstaticvoid main(String[] args){ GUI guiObj = new GUI(); }//end main }//end controlling class Affine01 class GUI extends Frame{ int res;//store screen resolution here staticfinalint ds = 72;//default scale, 72 units/inch GUI(){//constructor //Get screen resolution res = Toolkit.getDefaultToolkit(). getScreenResolution(); //Set Frame size to four-inches by four-inches this.setSize(4*res,4*res); this.setVisible(true); this.setTitle("Copyright 1999, R.G.Baldwin"); //Window listener to terminate program. this.addWindowListener(new WindowAdapter(){ publicvoid windowClosing(WindowEvent e){ System.exit(0);}}); }//end constructor //Override the paint() method to draw and manipulate a // square. publicvoid paint(Graphics g){ //Downcast the Graphics object to a Graphics2D object Graphics2D g2 = (Graphics2D)g; //Display contents of default AffineTransform object System.out.println("Default Transform"); displayMatrix(g2.getTransform()); //Update transform to include a scale component, // and display the values. System.out.println("Add Scale Transform"); g2.scale((double)res/72,(double)res/72); displayMatrix(g2.getTransform()); //Update transform to include a translate component, // and display the values. System.out.println("Add Translate Transform"); g2.translate(0.25*ds,0.25*ds); displayMatrix(g2.getTransform()); //Update transform to include a shear component, // and display the values. System.out.println("Add Shear Transform"); g2.shear(0.05,0.1); displayMatrix(g2.getTransform()); //Update transform to provide rotation and display, // the transform values. System.out.println("Add Rotate Transform"); //11.25 degrees about center g2.rotate(Math.PI/16,2.0*ds, 2.0*ds); displayMatrix(g2.getTransform()); //Draw five concentric squares and apply the transform // that results from the above transform updates. If // the above scale transform is applied, the outer // square is one inch on each side, and the squares // are separated by 0.1 inch double delta = 0.1; for(int cnt = 0; cnt < 5; cnt++){ g2.draw(new Rectangle2D.Double( (1.5+cnt*delta)*ds, (1.5+cnt*delta)*ds, (1.0-cnt*2*delta)*ds, (1.0-cnt*2*delta)*ds)); }//end for loop //Superimpose some text on the squares with the // lower left corner of the first character at the // center of the squares. g2.drawString("Exit ->",2.0f*ds,2.0f*ds); }//end overridden paint() //This method receives a reference to an AffineTransform // and displays the six controllable values in the // transform matrix void displayMatrix(AffineTransform theTransform){ double[] theMatrix = newdouble[6]; theTransform.getMatrix(theMatrix); //Display first row of values by displaying every // other element in the array starting with element // zero. for(int cnt = 0; cnt < 6; cnt+=2){ System.out.print(theMatrix[cnt] + " "); }//end for loop //Display second row of values displaying every // other element in the array starting with element // number one. System.out.println();//new line for(int cnt = 1; cnt < 6; cnt+=2){ System.out.print(theMatrix[cnt] + " "); }//end for loop System.out.println();//end of line System.out.println();//blank line }//end displayMatrix }//end class GUI //==============================//
想要了解更多開發(fā)技術(shù),面試教程以及互聯(lián)網(wǎng)公司內(nèi)推,歡迎關(guān)注我的微信公眾號!將會(huì)不定期的發(fā)放福利哦~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/69044.html
摘要:什么是為執(zhí)行字節(jié)碼提供一個(gè)運(yùn)行環(huán)境。它的實(shí)現(xiàn)主要包含三個(gè)部分,描述實(shí)現(xiàn)規(guī)格的文檔,具體實(shí)現(xiàn)和滿足要求的計(jì)算機(jī)程序以及實(shí)例具體執(zhí)行字節(jié)碼。該類先被轉(zhuǎn)化為一組字節(jié)碼并放入文件中。字節(jié)碼校驗(yàn)器通過字節(jié)碼校驗(yàn)器檢查格式并找出非法代碼。 什么是Java Development Kit (JDK)? JDK通常用來開發(fā)Java應(yīng)用和插件。基本上可以認(rèn)為是一個(gè)軟件開發(fā)環(huán)境。JDK包含Java Run...
摘要:本文簡介類概覽類構(gòu)造器總結(jié)類構(gòu)造方法類使用舉例類概覽是一個(gè)實(shí)現(xiàn)了接口,并且鍵為型的哈希表。中的條目不再被正常使用時(shí),會(huì)被自動(dòng)刪除。它的鍵值均支持。和絕大多數(shù)的集合類一樣,這個(gè)類不是同步的。 本文簡介 WeakHashMap類概覽 WeakHashMap類構(gòu)造器總結(jié) WeakHashMap類構(gòu)造方法 WeakHasjMap類使用舉例 1. WeakHashMap類概覽 Wea...
摘要:否則它就會(huì)用新的值替代當(dāng)前值。在這種情況下,鎖可能會(huì)優(yōu)于原子變量,但在實(shí)際的爭用級別中,原子變量的性能優(yōu)于鎖。在中引入了另外一個(gè)構(gòu)件。 題目要求 在我們深入了解CAS(Compare And Swap)策略以及它是如何在AtomicInteger這樣的原子構(gòu)造器中使用的,首先來看一下這段代碼: public class MyApp { private volatile int ...
摘要:這個(gè)例子想要說明兩個(gè)事情中以為結(jié)尾的方法將會(huì)異步執(zhí)行默認(rèn)情況下即指沒有傳入的情況下,異步執(zhí)行會(huì)使用實(shí)現(xiàn),該線程池使用一個(gè)后臺(tái)線程來執(zhí)行任務(wù)。這個(gè)例子展示了如何使用一個(gè)固定大小的線程池來實(shí)現(xiàn)大寫操作。 前言 這篇博客回顧JAVA8的CompletionStageAPI以及其在JAVA庫中的標(biāo)準(zhǔn)實(shí)現(xiàn)CompletableFuture。將會(huì)通過幾個(gè)例子來展示API的各種行為。 因?yàn)镃ompl...
摘要:在此基礎(chǔ)上又向前邁進(jìn)了一步局部變量類型推斷允許開發(fā)人員跳過局部變量的類型聲明局部變量是指在方法定義,初始化塊,循環(huán)和其它的如代碼塊,會(huì)推斷該局部變量的類型。 前言 之前面試的時(shí)候問了我是否了解JDK10的變化,一時(shí)回答不出來,所以只回答了JDK8中的函數(shù)式編程和流編程。今天看到這篇講JAVA10的文章,順便了解一下。 正文 JAVA10的所有新特性請參考這里。在所有的JEP中,JEP-...
閱讀 3793·2021-11-12 10:34
閱讀 2812·2021-09-22 15:14
閱讀 778·2019-08-30 15:53
閱讀 3196·2019-08-30 12:53
閱讀 1280·2019-08-29 18:32
閱讀 2761·2019-08-29 16:41
閱讀 1056·2019-08-26 13:40
閱讀 1795·2019-08-23 18:07