<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Pudgy's World
    posts - 13,  comments - 16,  trackbacks - 0

    摘自http://www-128.ibm.com/developerworks/cn/xml/x-BatikSvg/?ca=dwcn-newsletter-xml
    陳柯

    技術(shù)總監(jiān), 南京安元科技
    2005 年 1 月

    本文是作者在 SVGGIS 系統(tǒng)的開發(fā)實踐過程中關(guān)于 SVG 坐標轉(zhuǎn)換的總結(jié)。在描述 SVG 坐標變換原理的同時,使用 Apache Batik 項目實現(xiàn)了相關(guān)例子。

    SVG 是一種用 xml 語言來描述二維圖形對象的語言,SVG 允許三種圖形對象:1.矢量圖形,2.圖片,3.文本對象。這三種圖形對象都可以支持分組,使用樣式渲染,進行幾何變換。

    SVG 還能夠通過腳本來實現(xiàn)交互操作和動態(tài)顯示。可以通過定義動畫對象或使用script 腳本來實現(xiàn)動畫。

    1. SVG 下幾種常見的幾何變換方式

    1.1 一個 SVG 例子
    我們首先來看一個 SVG 的例子,窗口右上角有四個色塊,每個色塊是一個50×50的矩形。

    圖 1. 一個 SVG 的樣本
    圖 1. 一個 SVG 的樣本

    圖 2. 樣本文檔
    
    <?xml version="1.0"?>
    <svg >
        <g> 
    	<rect x="0" y="0" width="50" height="50" style="fill:red" />
    	<rect x="50" y="0" width="50" height="50" style="fill:yellow" />
    	<rect x="0" y="50" width="50" height="50" style="fill:green" />
    	<rect x="50" y="50" width="50" height="50" style="fill:black" />
        </g>
    </svg>
    

    1.2 使用 Adobe SVG Viewer 展示在 SVG 文檔中實現(xiàn)的幾何變換
    縮放<g transform="scale(2)">

    圖 3. 放大一倍
    圖 3. 放大一倍

    平移<g transform="translate(200 ,200)">

    圖 4. 平移200,200個像素
    圖 4. 平移200,200個像素

    旋轉(zhuǎn)<g transform="rotate(45)">

    圖 5. 順時針旋轉(zhuǎn)45度
    圖 5. 順時針旋轉(zhuǎn)45度

    橫切<g transform="skewX(45)">

    圖 6. 以 y 軸為基線在 X 方向橫切45度
    圖 6. 以 y 軸為基線在 X 方向橫切45度

    2. 在 Batik 下實現(xiàn) SVG 的幾何變換

    2.1 Batik 的基礎(chǔ)知識
    2.1.1 Batik 的用途

    Batik 是基于 java 語言實現(xiàn)的一個 SVG 應(yīng)用的工具集,用于實現(xiàn)對 SVG 對象的顯示、編輯以及將 SVG 圖形對象轉(zhuǎn)換成其他圖片格式,如 jpg、gif 等。

    這個項目的目標就是給開發(fā)人員一套用于處理或應(yīng)用 SVG 對象的基礎(chǔ)核心模型。作為Apache 項目成員之一,該項目也為開發(fā)人員提供了一個開發(fā)的可擴展的平臺。同時 batik 也維護了一個可以查看 SVG 文件的瀏覽器。雖然 batik 還沒有完全實現(xiàn) SVG 的所有標準語法和標記,但通過比較不同版本的區(qū)別就會發(fā)現(xiàn),他正在以很高的效率覆蓋 SVG 所有的標準。

    2.1.2 讓我們實現(xiàn)一個簡單的 Batik 程序

    首先讓我們實現(xiàn)一個簡單的基于 Batik 的 SVG 瀏覽器。Batik 封裝了org.apache.batik.swing.JSVGCanvas 對象可以用于在 swing 中嵌入 SVG 顯示容器,并可以通過 org.apache.batik.swing.JSVGCanvas 提供的方法對 SVG 文檔和圖像進行操作。這個瀏覽器可以支持大部分 SVG 的語法和標準包括腳本交互的功能,但暫時還沒有引入動畫。關(guān)于動畫和腳本交互的內(nèi)容我們會在以后的文章中講述,今天先集中解決幾何變換的問題。

    圖 7. 運行程序打開我們編寫的 SVG 的例子
    圖 7. 運行程序打開我們編寫的 SVG 的例子

    可以通過該頁面引導(dǎo)運行該程序:
    從附件中可以查看該程序的完整代碼,也可通過 網(wǎng)上下載地址 運行該程序。

    圖 8. 將一個 SVGCanvas 添加到界面
    
    private javax.swing.JPanel SVGPanel = new javax.swing.JPanel();
    private JSVGCanvas svgCanvas = new org.apache.batik.swing.JSVGCanvas();
    SVGPanel.add("Center", svgCanvas);
    

    2.2 通過 Batik 的 GVT 模型實現(xiàn) SVG 的幾何變換
    2.2.1 為什么要使用 Batik 來實現(xiàn) SVG 的幾何變換

    當我們用 Batik 工具集作為 SVG 客戶端的解決方案時,如縮放平移這樣的操作就在所難免了。但 Batik 并沒有直接支持如 Adobe SVG Viewer 那樣的鼠標拖動幾何變換的操作,這就要求我們對這些功能進行編程處理。

    在分析 SVG 的幾何變換的細節(jié)之前,先讓我們了解一下基本的操作編程方式。

    2.2.2 Batik 下通過 java.awt.geom.AffineTransform 來實現(xiàn) SVG 的幾何變換

    JSVGCanvas 提供方法可以獲取 java.awt.geom.AffineTransform 對象。AffineTransform 是用于實現(xiàn)2D 幾何圖形坐標變換處理的對象,可以通過該對象進行二維幾何空間中兩個坐標系的相互映射和變換。

    平移:


    
    //向左和向下平移50個像素
    java.awt.geom.AffineTransform  rat = svgCanvas.getRenderingTransform();
    rat.translate(50,50);
    svgCanvas.setRenderingTransform(rat);
    

    縮放:


    
    //以屏幕左上角原點為固定點進行縮放操作
    java.awt.geom.AffineTransform  rat = svgCanvas.getRenderingTransform();
    rat.scale(0.5,0.5);
    svgCanvas.setRenderingTransform(rat);
    

    旋轉(zhuǎn):


    
    //以屏幕左上角原點為固定點進行旋轉(zhuǎn)縮放
    java.awt.geom.AffineTransform  rat = svgCanvas.getRenderingTransform();
    rat.rotate(3.1415926/4);
    svgCanvas.setRenderingTransform(rat);
    

    復(fù)合變換:


    
    //一個綜合平移、放大和旋轉(zhuǎn)90度的復(fù)合變換
    java.awt.geom.AffineTransform  rat = svgCanvas.getRenderingTransform();
    rat.translate(50,50);
    rat.scale(2,2);
    rat.rotate(3.1415926/4);
    svgCanvas.setRenderingTransform(rat);
    

    3. 當我們需要進行復(fù)合幾何變換的時候

    3.1 先來讓我們通過不同的變換代碼組合實現(xiàn)復(fù)合幾何變換
    先讓我們看第一個例子:

    //放大一倍和平移50個像素的復(fù)合變換
    
    AffineTransform rat = svgCanvas.getRenderingTransform();
    
            rat.scale(2,2);
    rat.translate(50,50);
    svgCanvas.setRenderingTransform(rat);
    
          

    圖 9. 復(fù)合變換一
    圖 9. 復(fù)合變換一

    可以看得出來,這個變換的最終效果是:圖形的形狀放大一倍,原圖形的(0,0)原點坐標平移100個像素。

    再來看第二個例子:


    
    //放大一倍和平移50個像素的復(fù)合變換
    AffineTransform rat = svgCanvas.getRenderingTransform();
    
            rat.translate(50,50);
    rat.scale(2,2);
    svgCanvas.setRenderingTransform(rat);
    
          

    圖 10. 復(fù)合變換二
    圖 10. 復(fù)合變換二

    這個變換的最終效果是:圖形的形狀放大一倍,原圖形的(0,0)原點坐標平移50個像素。

    3.2 關(guān)鍵是順序
    比較一下這兩種平移后的效果會發(fā)現(xiàn),只是因為縮放和平移的順序不同,變換后的結(jié)果就發(fā)生了區(qū)別。第一個例子實際平移的不是50個像素,而是100個像素。而第二個例子則是平移了50個像素。

    有興趣的讀者可以添加其他幾何變換方式,并測試不同的變換順序,會發(fā)現(xiàn)復(fù)合變換的順序與復(fù)合變換的最終效果是緊密相關(guān)的。那么如何分析和計算復(fù)合變換的變換結(jié)果呢?這里我們需要補充一點數(shù)學知識了。

    3.3 對單一的幾何變換進行數(shù)學模型分析
    對計算機圖形學中圖形變換相關(guān)理論很熟悉的人可以跳過這部分直接看 Batik 的實現(xiàn)方式。這節(jié)使用的齊次式圖片引用自 SVG標準中關(guān)于坐標變換的齊次式的例子插圖。

    首先我們來了解一下圖形變換的齊次式計算方法:

    圖 11. 基本幾何 變換齊次式
    圖 11. 基本幾何 變換齊次式

    這是一個基本圖形變換齊次式。等式的最右邊是一個坐標點未變換前的坐標矩陣,最左邊是該坐標點變換后所在位置的一個三行一列的坐標矩陣,中間那個三行三列的矩陣就是變換矩陣。不同的變換方式將對應(yīng)不同的變換矩陣,圖形平移效果就是通過這樣一個變換齊次式來實現(xiàn)的。

    平移:如果需要將圖形平移(tx,ty)個坐標時,采用如下的變換矩陣帶入變換方程。

    圖 12. 平移變換矩陣
    圖 12. 平移變換矩陣

    縮放:如果需要在 x 軸方向?qū)崿F(xiàn) sx 倍縮放,在 y 軸方向?qū)崿F(xiàn) sy 軸縮放時,采用如下的變換矩陣帶入變換方程。

    圖 13. 縮放變換矩陣
    圖 13. 縮放變換矩陣

    旋轉(zhuǎn):如果需要將圖像旋轉(zhuǎn) a 度時,使用如下的變換矩陣帶入變換方程。

    圖 14. 旋轉(zhuǎn)變換矩陣
    圖 14. 旋轉(zhuǎn)變換矩陣

    3.4 采用復(fù)合幾何變換的數(shù)學模型分析
    3.4.1 數(shù)學分析

    當兩組變換同時作用于同一個圖像時,連續(xù)使用該等式,得出如下等式。由于做變換的時候是將變換矩陣放在矩陣積的左邊,所以對于復(fù)合變換的式子,應(yīng)該從右向左進行讀。對于如下的式子:從右至左依次是變換前的坐標,第一次轉(zhuǎn)換的轉(zhuǎn)換矩陣,第二次轉(zhuǎn)換的轉(zhuǎn)換矩陣,轉(zhuǎn)換后的坐標值。

    圖 15. 進行兩次變換的復(fù)合矩陣
    圖 15. 進行兩次變換的復(fù)合矩陣

    進一步推導(dǎo) n 次幾何變換的復(fù)合變換等式:

    圖 16. n次變換的復(fù)合矩陣
    圖 16. n次變換的復(fù)合矩陣

    3.4.2 來實踐一下

    圖 17. 變換前效果
    圖 17. 變換前效果

    使用這樣一個復(fù)合變換方式:

    <g transform="translate(50,90) rotate(-45) translate(130,160)">

    根據(jù)前面的分析結(jié)果帶入變換方程,得出如下等式

    圖 18. 推導(dǎo)矩陣
    圖 18. 推導(dǎo)矩陣

    根據(jù)計算后的變換矩陣,可得變換結(jié)果是圖形整體平移到(255.03,111.21),同時圖形自身沿順時針方向旋轉(zhuǎn)45度。查看實際變換結(jié)果,這里我們可以發(fā)現(xiàn),對于 SVG 的變換來說,雖然我們習慣上從左往右寫變換參數(shù)的,實際上圖形做變換的時候是從右邊的變換參數(shù)開始依次進行圖形變換的。

    圖 19. 變換后效果
    圖 19. 變換后效果

    3.5 分析一下 Batik 是如何實現(xiàn) SVG 的復(fù)合幾何變換的
    3.5.1 先看第一個例子:

    這個變換是先放大后平移的變換,其變換效果最終是,先將圖形的形狀放大一倍,然后將圖形整個平移100個像素。這里我們可以看出,雖然我們是先進行的放大變換,后進行的平移操作,但當我們進行復(fù)合變換的時候由于實際運算時上是先進行了平移,后進行了縮放。或者簡單的理解為從左向右先寫縮放矩陣,再寫平移矩陣,這樣得出的變換矩陣就可以對變換后的效果進行計算了。


    
    //放大一倍和平移50個像素的復(fù)合變換
    //<g transform=" scale(2 ) translate(50 50)">
    AffineTransform rat = svgCanvas.getRenderingTransform();
    
            rat.scale(2,2);
    rat.translate(50,50);
    svgCanvas.setRenderingTransform(rat);
    
          

    我們可以將這個變換對應(yīng)的計算矩陣寫出來:

    圖 20. 復(fù)合變換例一的變換矩陣
    圖 20. 復(fù)合變換例一的變換矩陣

    根據(jù)上面的分析我們可以看的出,先進行縮放變換在進行平移變換的復(fù)合變換時,變換后原圖元的坐標會映射到新的位置,其中:

    X1=Sx(X+dx)
    Y1=Sy(Y+dy)

    3.5.2 再來看第二個例子:

    這個變換是先放大后平移的變換,其變換效果最終是,先將圖形整個平移50個像素,然后將圖形的形狀放大一倍。


    
    //放大一倍和平移50個像素的復(fù)合變換
    //<g transform="translate(50,50) scale(2 )">
    AffineTransform rat = svgCanvas.getRenderingTransform();
    
            rat.translate(50,50);
    rat.scale(2,2);
    svgCanvas.setRenderingTransform(rat);
    
          

    我們可以將這個變換對應(yīng)的 svg 文檔實現(xiàn)寫出來:

    <g transform="translate(50 50) scale(2 )">

    圖 21. 復(fù)合變換例二的變換矩陣
    圖 21. 復(fù)合變換例二的變換矩陣

    根據(jù)上面的分析我們可以看的出,先進行平移變換再進行縮放變換的復(fù)合變換時,變換后原圖元的坐標會映射到新的位置,其中:

    X1=Sx*X+dx
    Y1=Sy*Y+dy

    3.5.3 實用這兩個例子的成果

    假設(shè)我們需要將圖形原點的位置移動到(150,300),同時形狀放大到原來的3倍,該如何進行變換來實現(xiàn)這樣的效果呢?

    圖 22. 變換效果
    圖 22. 變換效果

    使用第一個例子的分析結(jié)果,先進行縮放變換,再進行平移變換的方程變換:

    圖 23. 方程推演
    圖 23. 方程推演

    根據(jù)推導(dǎo)可知需先進行3倍的縮放變換,再平移(50,100)個坐標就可以實現(xiàn)指定的變換效果。實現(xiàn)程序如下


    
    //<g transform=" scale(3 ) translate(50,100)">
    AffineTransform rat = svgCanvas.getRenderingTransform();
    
            rat.scale(3,3);
    rat.translate(50,100);
    svgCanvas.setRenderingTransform(rat);
    
          

    若先進行平移變換,再進行縮放變換的話,根據(jù)第二個例子的推導(dǎo)結(jié)果:

    圖 24. 方程推演
    圖 24. 方程推演

    可知應(yīng)先進行(150,300)的平移操作,再實現(xiàn)3倍的縮放操作。實現(xiàn)程序如下:


    
    //<g transform=" translate(150,300) scale(3 )">
    AffineTransform rat = svgCanvas.getRenderingTransform();
    
            rat.translate(150,300);
    rat.scale(3,3);
    svgCanvas.setRenderingTransform(rat);
    
          

    4. 一個常用復(fù)合變換實例的實現(xiàn)--定點變換
    上邊我們分析了 Batik 實現(xiàn) SVG 圖形變換的原理和計算方法。下面我們用分析的結(jié)果實現(xiàn)一個常用的變換實例:定點變換。變換的種類包括縮放,旋轉(zhuǎn)(一般不考慮定點平移這個概念)。

    所謂定點變換就是在圖形變換中指定一個固定的點,在變換結(jié)束后,該點的位置不發(fā)生變化。定點變換在 GIS 的實際運用中很常見,比如將地圖放大到指定倍數(shù)而保持地圖的某個位置(如:鼠標點擊的位置)不發(fā)生變化。我們以定點縮放為例描述定點變換的使用方法。

    假設(shè)我們用(x1,y1)點來做定點變換的基準點進行幾何變換,要求實現(xiàn)變換后(x1,y1)的位置不變。

    定點變換的基本思想是基于這樣一個特性:當圖像進行縮放,或旋轉(zhuǎn)變換的時候,坐標原點的位置并不發(fā)生變化。定點變換的實現(xiàn)方法就是,先將基準點(x1,y1)平移到原點即做一次[-x1,-y1]變換,進行變換后再將變換后的原點平移到(x1,y1)即再進行一次[x1,y1]變換。

    圖 25. 基于(x1,y1)定點變換
    圖 25. 基于(x1,y1)定點變換

    實際編程的時候,我們無需對定點變換做如此復(fù)雜的運算。例如可以采用如下的方式實現(xiàn)針對(50,50)的定點變換:


    
    //以(50,50)點為基準點進行幾何變換
    //<g transform="translate(50,50) …………… translate(-50,-50)">
    AffineTransform rat = svgCanvas.getRenderingTransform();
    
            rat.translate(50,50);
    //其他變換方式
    ………………
    ………………
    ………………
    rat.translate(-50,-50);
    svgCanvas.setRenderingTransform(rat);
    
          

    參考資料

    posted on 2005-08-20 08:55 Pudgy's World 閱讀(2492) 評論(0)  編輯  收藏 所屬分類: Graphics

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     

    <2005年8月>
    31123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    常用鏈接

    留言簿(1)

    隨筆分類(13)

    隨筆檔案(13)

    文章分類(4)

    文章檔案(5)

    相冊

    Developer

    Favorite blogs

    搜索

    •  

    積分與排名

    • 積分 - 22403
    • 排名 - 1627

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 1区2区3区产品乱码免费| 精品亚洲福利一区二区| 久操视频免费观看| 国产午夜亚洲不卡| 中国好声音第二季免费播放| 亚洲熟妇av一区二区三区| 97在线视频免费公开视频| 国产偷v国产偷v亚洲高清| 日本三级在线观看免费| 亚洲精品国产成人99久久| 日本人的色道免费网站| 亚洲中文无码永久免| 国产在线不卡免费播放| 国产高潮流白浆喷水免费A片 | 亚洲精品成人片在线观看精品字幕| 中文字幕乱码一区二区免费| 国产aⅴ无码专区亚洲av| h在线观看视频免费网站| 亚洲欧洲无码AV不卡在线| 亚洲精品无码99在线观看| 十八禁视频在线观看免费无码无遮挡骂过 | 亚洲视频中文字幕| 91免费播放人人爽人人快乐| 亚洲国产成人久久综合| 亚洲人成无码久久电影网站| 亚洲视频免费在线观看| 亚洲国产精品免费观看 | 91香蕉在线观看免费高清| 亚洲一区二区久久| 免费国产精品视频| 免费国产99久久久香蕉| 麻豆狠色伊人亚洲综合网站| 又黄又爽无遮挡免费视频| 最近免费中文字幕大全高清大全1| 亚洲av成人一区二区三区在线播放| 国产av无码专区亚洲av果冻传媒| 亚洲免费观看在线视频| 麻豆一区二区三区蜜桃免费| 亚洲精选在线观看| 国产一区二区三区在线免费观看| 午夜无码A级毛片免费视频|