AGG第二十一課agg::conv_contour擴展輪廓線

1前言

輪廓線就是圖形的邊界,任何封閉的頂點源跳過agg::conv_stroke階段,將會描繪實心的圖形,填充的顏色和邊界保持一致。如果不封閉的頂點源一旦跳過agg::conv_stroke就什么也不繪制。agg::conv_stroke就是用來描繪圖形邊界的。

10年的洞頭網站建設經驗,針對設計、前端、開發(fā)、售后、文案、推廣等六對一服務,響應快,48小時及時工作處理。成都全網營銷推廣的優(yōu)勢是能夠根據用戶設備顯示端的尺寸不同,自動調整洞頭建站的顯示方式,使網站能夠適用不同顯示終端,在瀏覽器中調整網站的寬度,無論在任何一種瀏覽器上瀏覽網站,都能展現優(yōu)雅布局與設計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯從事“洞頭網站設計”,“洞頭網站推廣”以來,每個客戶項目都認真落實執(zhí)行。

和agg::trans_affine對比可知,agg::conv_contour是擴展圖形的輪廓線,通俗一點就是拓展圖形的邊界,對圖形的邊界進行放縮(但是和agg::trans_affine仿射變換不同,這是中心位置不變的縮放)。

2 官方例子

       執(zhí)行examples/conv_stroke例程,提供如下的控制:

1)線段端點的切換

2)線段之間的連接方式

3)線段寬度

 

3代碼分析

頭文件:#include"agg/include/agg_conv_stroke.h"

1)線段端點的形狀

   enum line_cap_e

    {

       butt_cap,//按鈕形狀,實際和方形形狀并無二致

       square_cap,//設置之后,長度比butt_cap長一些

       round_cap//半圓形狀

};

設置函數:voidline_cap(line_cap_e lc)

2)線段的寬度

設置函數:voidwidth(double w)

3)介紹stroke的默認參數

當然我們可以不調用line_cap,也可以不調用width,因為stroke有默認的構造器,指定了默認的參數如下:

       m_width(0.5),

       m_width_abs(0.5),

       m_width_eps(0.5/1024.0),

       m_width_sign(1),

       m_miter_limit(4.0),

       m_inner_miter_limit(1.01),

       m_approx_scale(1.0),

       m_line_cap(butt_cap),

       m_line_join(miter_join),

       m_inner_join(inner_miter)

4)agg::conv_stroke的線段樣式

采用的是實線的渲染方式,是否我們可以通過替換她,描述虛線:agg::conv_dash

結果發(fā)現:什么也沒有渲染出來!!agg::conv_dash會單獨描述??!

3 例子

ras.reset();

   agg::path_storage ps1;

   ps1.move_to(200,200);

   ps1.line_to(300,300);

 

   agg::line_cap_e cap = agg::round_cap;//設置線段端點的形狀

   agg::conv_stroke<agg::path_storage> stroke(ps1);//線段的樣式

   stroke.line_cap(cap);

   stroke.width(50);//設置線段的寬度

   ras.add_path(stroke);

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

 

 

2 agg::conv_contour輪廓變換

1 分析

       輪廓線是圖形的輪廓邊界,擴展輪廓線也就是在圖形的中心位置不變的情況下,邊界進行了放縮,和affine的仿射縮放不同,后者是中心位置也會產生偏移,針對于圓形非常好理解,可以嘗試對一個圓形分別進行agg::conv_contour和agg::trans_affine處理,可以看到明顯的效果:

agg::conv_contour原地膨脹

agg::trans_affine圓心偏移,并且放縮

3.3 例子回放

   //Vertex Source

   agg::ellipse ell(100,100,50,50);

 

   // Coordinate conversion pipeline

   typedef agg::conv_contour<agg::ellipse> ell_cc_type;

   ell_cc_type ccell(ell);

 

   typedef agg::conv_stroke<ell_cc_type> ell_cc_cs_type;

   ell_cc_cs_type csccell(ccell);

 

   // Draw

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

   for(int i=0; i<3; i++)

    {

     ccell.width(i*50);//看清楚,這是對輪廓線的實例進行的操作,而不是stroke實例

     ras.add_path(csccell);

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

}

分析:當i = 0的時候,并沒有進行輪廓的放縮,可以清晰的了解到,進行輪廓放縮的時候,圓形變大了,實際上是圓形的輪廓邊界放大的緣故,但是圓心不變!!

3 圖形處理流程

網上提供的一般邏輯:

矩陣變換agg::conv_transform

輪廓邊界擴展(實際上是邊界縮放)agg::conv_contour

轉換成多義線(顯示輪廓線)agg::conv_stroke

再次重申:agg::conv_contour和agg::conv_stroke作為“坐標轉換管道Coordinateconversion pipeline”,conv_contour擴展輪廓線,conv_stroke只顯示輪廓線(如果沒有conv_stroke就會顯示實心圓,可以去掉試試)。

 

4代碼分析

conv_contour實際上是由vcgen_contour

真正實現的!!幾乎所有的實現都是調用了vcgen_contour

的generator函數

 

 

一個簡單的測試例子:

   agg::ellipse ell(100,100,50,50);

 

   agg::trans_affine mtx;

   mtx.scale(2,1);

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

   ell_ct_type ctell(ell, mtx);

 

   /************/

   typedef agg::conv_contour<ell_ct_type> ell_cc_type;

   ell_cc_type ccell(ctell); // 輪廓變換

   ccell.width(6);//nothing happen

   /************/

 

   typedef agg::conv_stroke<ell_cc_type> ell_cc_cs_type;

   ell_cc_cs_type csccell(ccell);

   //csccell.width(6);

 

   ras.add_path(ccell);

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

5 auto_detect_orientation函數

       正如名稱所言:自動檢測方向,什么方向,可能很多人不了解,通過AGG郵件了解到幾點:擴展輪廓線跟圖形的繪制方向有關(也就是move_to,line_to,構成的圖形的順時針,還是逆時針)。如下的兩個例子,一個是順時針繪制矩形,一個是逆時針繪制矩形,然后擴展輪廓線。

例子1逆時針

   agg::path_storage ps;

   ps.move_to(395.5,200.5);

   ps.line_to(295.5,200.5);

   ps.line_to(295.5,210.5);

   ps.line_to(395.5,210.5);

ps.close_polygon();

agg::conv_contour<agg::path_storage> contour(ps);

//contour.auto_detect_orientation(true);

contour.width(m_slider1.value());//獲取滑動條的值

agg::conv_stroke<agg::conv_contour<agg::path_storage> >stroke(contour);

 ras.add_path(stroke);

 

例子2 順時針

    agg::path_storage ps;

    ps.move_to(395.5,200.5);

    ps.line_to(395.5,210.5);

    ps.line_to(295.5,210.5);

ps.line_to(295.5,200.5);

    agg::conv_contour<agg::path_storage>contour(ps);

    contour.width(m_slider1.value());

   agg::conv_stroke<agg::conv_contour<agg::path_storage> >stroke(contour);

ras.add_path(stroke);

 

結果分析:第二個例子順利的進行擴展線的放大或縮小,但是第一個例子剛好相反,兩個例子之間的區(qū)別就是圖形繪制的方向不同而已。所以為了解決這種問題,才引入了contour.auto_detect_orientation函數。

把第一個例子的上面函數去掉注釋,就可以按照正常的邏輯進行縮放輪廓線。

6 width函數參數意義探究

AGG里面大部分的函數參數都是需要高深的圖形計算的知識,探究源碼更是需要深厚的功底。所以現在只能夠通過函數的調用,然后通過顯示的圖形,推導出該函數的具體含義。

    結論如下:當前是通過規(guī)則的圓形來示范發(fā)現,當設置width參數為200的時候,半徑是增加了100,其中的100都是以像素作為單位。每一個像素代表一個坐標點。

如下是詳細的代碼:

 void TestContourValue()

  {

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

 

   typedef agg::renderer_scanline_aa_solid<renderer_base_type>renderder_scanline_type;

   renderder_scanline_type rensl(renb);

 

   agg::rasterizer_scanline_aa<> ras;

   agg::scanline_u8 sl;

   ras.reset();

 

   agg::path_storage ps;

   ps.move_to(200,200);

   ps.line_to(400,200);

   ps.line_to(400,400);

   ps.line_to(200,400);

   ps.close_polygon();

   agg::conv_stroke<agg::path_storage> stroke(ps);

   ras.add_path(stroke);

 

   agg::ellipse ell(300,300,100,100);

   agg::conv_stroke<agg::ellipse> stroke1(ell);

   ras.add_path(stroke1);

 

   ps.remove_all();

   ps.move_to(100,100);

   ps.line_to(500,100);

   ps.line_to(500,500);

   ps.line_to(100,500);

   ps.close_polygon();

   agg::conv_stroke<agg::path_storage> stroke2(ps);

   ras.add_path(stroke2);

 

   agg::conv_contour<agg::ellipse> contour(ell);

   contour.width(200);

   agg::conv_stroke<agg::conv_contour<agg::ellipse> >stroke3(contour);

   ras.add_path(stroke3);

 

   ps.remove_all();

   ps.move_to(0,0);

   ps.line_to(600,0);

   ps.line_to(600,600);

   ps.line_to(0,600);

   ps.close_polygon();

   agg::conv_stroke<agg::path_storage> stroke4(ps);

   ras.add_path(stroke4);

 

 

   agg::conv_contour<agg::ellipse> contour1(ell);

   contour1.width(400);

   agg::conv_stroke<agg::conv_contour<agg::ellipse> >stroke5(contour1);

   ras.add_path(stroke5);

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

  }

7 擴展輪廓的限制

agg::conv_contour無法應用于自交的圖形

測試代碼:

 void DrawIntersectContour()

  {

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

 

   typedef agg::renderer_scanline_aa_solid<renderer_base_type>renderder_scanline_type;

   renderder_scanline_type rensl(renb);

 

   agg::rasterizer_scanline_aa<> ras;

   agg::scanline_u8 sl;

   ras.reset();

 

   agg::path_storage ps;

   ps.move_to(200,400);

   ps.line_to(500,500);

   ps.line_to(200,500);

   ps.line_to(500,400);

   ps.line_to(200,400);

 

   agg::conv_contour<agg::path_storage> contour(ps);

   agg::conv_stroke<agg::conv_contour<agg::path_storage> >stroke(contour);

   ras.add_path(stroke);

//    agg::conv_stroke<agg::path_storage> stroke1(ps);

//    ras.add_path(stroke1);

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

  }

結果分析:嘗試繪制一個三角形漏斗,但是通過擴展輪廓線模塊,發(fā)現沒有進行封閉,可通過取消注釋,查看具體的情況。實際上AGG提供的例子就是通過渲染a,實際上該字母本身就是自交的,導致了輪廓的放縮非常的奇怪??!

如下是作者的描述:

You can use conv_contour in your vectorpipeline. See

examples/conv_contour.cpp for details. Theonly problem is it won'twork for

self-intersecting contours, because thedirection of the polygons is

essential, but we can't talk about thepolygon direction if itintersects

itself.

當前文章:AGG第二十一課agg::conv_contour擴展輪廓線
本文網址:http://muchs.cn/article38/ihcosp.html

成都網站建設公司_創(chuàng)新互聯,為您提供微信公眾號搜索引擎優(yōu)化、外貿網站建設、全網營銷推廣、網站制作、建站公司

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

小程序開發(fā)