1. 程式人生 > >AGG第十八課 agg::trans_affine仿射變換

AGG第十八課 agg::trans_affine仿射變換

agg agg::trans_affine 仿射變換

1 affine仿射變換概念

在幾何上定義為兩個向量空間之間的一個仿射變換或者仿射映射(來自拉丁語,affinis"和。..相關")由一個線性變換接上一個平移組成。

2 agg::trans_affine成員函數說明

2.1 縮放

inline const trans_affine&trans_affine::scale(double x, double y)

參數一對x橫坐標的縮放系數,參數二對y縱坐標的縮放系數

這裏有一個問題:就是圖形的縮放之後,並不是在原有的位置上,進行縮放,而是整體的縮放,比如最明顯的是圓形,圓心的位置發生了改變,所以需要進行平移,恢復到以前的圓心。

2.2 旋轉

inline const trans_affine&trans_affine::rotate(double a)

參數對圖形進行旋轉,旋轉的圓心是坐標的原點(0,0,也就是顯示界面的左上角,和一般的笛卡爾坐標不一樣的地方,Y軸的縱坐標進行了翻轉,Y軸向下逐漸增大。

應用註意事項:參數采用的是弧度的形式,至於弧度(radians)和角度(degrees)之間的區別,請參考其他的章節,不再贅述。所以該參數的範圍是[-pi,pi].pi = 3.141592653.正值表示順時針旋轉,負值逆時針旋轉,旋轉的中心對稱點是(0,0),切記!!很可能會旋轉到界面之外。

Tips:角度轉弧度agg::deg2rad(doubledegrees)

2.3 平移

inline const trans_affine&trans_affine::translate(double x, double y)

參數一,X軸平移量,參數二,Y軸平移量

3 關於仿射變換的數學知識

本文不打算描述trans_affine仿射變換的基本原理,其中的代碼在agg_trans_affine.h文件中定義,涉及到的六個仿射變量如下:

double sx, shy, shx, sy, tx, ty;

可以搜索仿射變換的基本原理。

4 一些測試實例

4.1 旋轉出界面

實例代碼如下:

ras.reset();

agg::ellipse ell(400,400,20,70);

//坐標轉換

agg::trans_affine mtx;

//mtx.scale(0.5,1); //x軸縮小到原來的一半

mtx.rotate(agg::deg2rad(30));//旋轉

30

//mtx.translate(200,200);//XY坐標分別平移100

typedef agg::conv_transform<agg::ellipse> ell_ct_type;

ell_ct_type ctell(ell,mtx); //矩陣變換

ras.add_path(ctell);

agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba8(255,0,0));

ras.reset();

這是網上最經典的一個使用例子,但是並沒有說明旋轉是如何實現的,稍微修改了一下代碼:

mtx.rotate(agg::deg2rad(60));//旋轉60

結果:發現界面上什麽也沒有,橢圓不見了!!

原因:順時針旋轉出界面。

4.2 通過滑動條查看旋轉的過程

void RotateEclipse()

{

//關於agg::slider_ctrl<agg::rgba8>的基本使用,請參考其他的章節

int value = m_slider1.value();//取值

agg::rendering_buffer &rbuf = rbuf_window();

agg::pixfmt_bgr24 pixf(rbuf);

typedef agg::renderer_base<agg::pixfmt_bgr24> renderer_base_type;

renderer_base_type renb(pixf);

agg::rasterizer_scanline_aa<> ras;

agg::scanline_u8 sl;

ren_bas.clear(agg::rgba8(255,255,255));

agg::trans_affine mtx;

//mtx.scale(0.5,0.5); //x軸縮小到原來的一半

mtx.rotate(agg::deg2rad(value));//旋轉30

//mtx.translate(100 ,100);//XY坐標分別平移100

agg::ellipse ell(900,900,20,30);

typedef agg::conv_transform<agg::ellipse> ell_ct_type;

ell_ct_type ctell(ell,mtx); //矩陣變換

ras.reset();

ras.add_path(ctell);

agg::render_scanlines_aa_solid(ras,sl,renb,agg::rgba8(255,0,0));

agg::render_ctrl(ras, sl, renb, m_slider1);

}

5版本差異以及具體應用

1AGG2.3版本

目前已經很難下載到,早期的項目有應用到,沒有繼續更新!!

如下代碼對矩形進行縮放:

ras.reset();

agg::path_storage ps;

ps.move_to(30,30);

ps.line_to(50,30);

ps.line_to(50,50);

ps.line_to(30,50);

ps.line_to(30,30);

agg::trans_affine mtx;

//橫坐標放大2倍,縱坐標放大3

mtx*= agg::trans_affine_scaling(2, 3);

//橫坐標平移100,縱坐標平移300,正數向右,負數向左

mtx*=agg::trans_affine_translation(100,100);

typedefagg::conv_transform<agg::path_storage> ell_ct_type;

ell_ct_type ctell(ps,mtx); //矩陣變換

typedef agg::conv_stroke<ell_ct_type>ell_cc_cs_type;

ell_cc_cs_typecsccell(ctell);

ras.add_path(ctell);

2AGG2.4/2.5版本

agg::trans_affine mtx;

mtx.scale(0.5,0.5); //x軸縮小到原來的一半

mtx.rotate(agg::deg2rad(40));//旋轉30

mtx.translate(100 ,100);//XY坐標分別平移100

typedefagg::conv_transform<agg::path_storage> ell_ct_type;

ell_ct_type ctell(ps,mtx); //矩陣變換

typedef agg::conv_stroke<ell_ct_type>ell_cc_cs_type;

ell_cc_cs_type csccell(ctell);

ras.add_path(csccell);

6 摘自agg_trans_affine.h的翻譯

在笛卡爾坐標系中(Cartesian coordinates)仿射轉換(affine transformation)是一種線性的轉換(在一開始的時候就設定了)。她們可以自由的旋轉(rotation,縮放(scaling,平移(translation)和剪切變換(skewing.經過任意的仿射變換,線段仍然是線段,她永遠不可能編程一根曲線。

一言以蔽之,任何的矩陣變換都可以用一系列的離散變換實現。

原文如下:

//============================================================trans_affine

//

// See Implementation agg_trans_affine.cpp

//

// Affine transformation are lineartransformations in Cartesiancoordinates

// (strictly speaking not only inCartesian, but for the beginning wewill

// think so). They are rotation, scaling,translation and skewing.

// After any affine transformation a linesegment remains a line segment

// and it will never become a curve.

//

// There will be no math about matrixcalculations, since it has been

// described many times. Ask yourself avery simple question:

// "why do we need to understand anduse some matrix stuff insteadof just

// rotating, scaling and so on". Theanswers are:

//

// 1. Any combination of transformationscan be done by only 4multiplications

// and 4 additions in floatingpoint.

// 2. One matrix transformation isequivalent to the number ofconsecutive

// discrete transformations,i.e. the matrix "accumulates" alltransformations

// in the order of theirsettings. Suppose we have 4 transformations:

// * rotate by 30 degrees,

// * scale X to 2.0,

// * scale Y to 1.5,

// * move to (100, 100).

// The result will depend on theorder of these transformations,

// and the advantage of matrixis that the sequence of discret calls:

// rotate(30), scaleX(2.0),scaleY(1.5), move(100,100)

// will have exactly the sameresult as the following matrixtransformations:

//

// affine_matrix m;

// m *= rotate_matrix(30);

// m *= scaleX_matrix(2.0);

// m *= scaleY_matrix(1.5);

// m *= move_matrix(100,100);

//

// m.transform_my_point_at_last(x, y);

//

// What is the good of it? In real life wewill set-up the matrix onlyonce

// and then transform many points, letalone the convenience to set any

// combination of transformations.

//

// So, how to use it? Very easy - literallyas it‘s shown above. Notquite,

// let us write a correct example:

//

// agg::trans_affine m;

// m *= agg::trans_affine_rotation(30.0 *3.1415926 / 180.0);

// m *= agg::trans_affine_scaling(2.0,1.5);

// m *=agg::trans_affine_translation(100.0, 100.0);

// m.transform(&x, &y);

//

// The affine matrix is all you need toperform any lineartransformation,

// but all transformations have originpoint (0,0). It means that we needto

// use 2 translations if we want to rotatesometing around (100,100):

//

// m *= agg::trans_affine_translation(-100.0,-100.0); // move to (0,0)

// m *= agg::trans_affine_rotation(30.0 *3.1415926 / 180.0); // rotate

// m *=agg::trans_affine_translation(100.0, 100.0); // move back to (100,100)

//----------------------------------------------------------------------


AGG第十八課 agg::trans_affine仿射變換