亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Qt 實(shí)現(xiàn)鋼筆畫線效果示例及詳細(xì)原理

 更新時(shí)間:2020年04月08日 09:36:55   作者:luoyayun361  
這篇文章主要介紹了Qt 實(shí)現(xiàn)鋼筆畫線效果示例及詳細(xì)原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

上一篇文章:Qt 實(shí)現(xiàn)畫線筆鋒效果詳細(xì)原理,根據(jù)這篇介紹的實(shí)現(xiàn)筆鋒效果的原理,我們很容易實(shí)現(xiàn)另外一種筆效:鋼筆。

所謂的鋼筆筆效,就是真實(shí)還原鋼筆書寫出來的線條效果,其特征就是:根據(jù)筆的繪制速度而線條的寬度會(huì)逐漸變化,寫得越快,線條越細(xì),并且在收筆時(shí)帶有筆鋒效果。

那么,在上一篇文章的基礎(chǔ)上,稍微修改一下,就可以實(shí)現(xiàn)這個(gè)效果,看下效果圖:

實(shí)現(xiàn)原理

從上一篇文章我們知道,繪制的曲線是通過每兩個(gè)點(diǎn)形成一條貝塞爾曲線,所以在不松手的情況下連續(xù)畫線,整條線段是包含很多條path組合而成的。而要實(shí)現(xiàn)鋼筆效果的關(guān)鍵,是要讓線條的粗細(xì)跟隨繪制的速度來變化。

之前看過很多Android上實(shí)現(xiàn)鋼筆或者毛筆的算法,都是需要計(jì)算去畫線速度,根據(jù)速度來動(dòng)態(tài)改變線條的粗細(xì)。但是我這里沒有計(jì)算速度,而是直接通過每一段path的長度來計(jì)算一個(gè)合理的寬度值出來。

眾所周知,長度(也就是距離)= 速度*時(shí)間,在單位時(shí)間內(nèi),速度和距離是成正比的,所以我們通過兩點(diǎn)間的距離來做判斷也是一樣的,沒多大區(qū)別,并且還不用單獨(dú)去計(jì)算速度了,簡單省事兒。

那么,我們要實(shí)現(xiàn)的效果是,畫線速度越快線條會(huì)越細(xì),而畫線速度越快,所采集到的兩點(diǎn)間的距離就會(huì)越大,而我們是通過兩點(diǎn)間距離來做參考依據(jù),也就是說,兩點(diǎn)間距和線條粗細(xì)是成反比的,兩點(diǎn)間距越長,對(duì)應(yīng)的這條path就越細(xì),距離越短,path就越粗,二者是線性關(guān)系。當(dāng)然,這里path的寬度會(huì)有一個(gè)最大值和最小值,需要在實(shí)際的場景中進(jìn)行調(diào)試。

OK,根據(jù)以上分析,我們可以得到以下的示意圖:

每條path都是通過兩個(gè)坐標(biāo)點(diǎn)實(shí)時(shí)生成的貝塞爾曲線。
在繪制這條曲線的時(shí)候,先獲取到曲線的長度,然后線性計(jì)算出一個(gè)寬度值。
如何獲取path的長度呢?
這個(gè)好辦,QPainterPath有自帶的接口length()

計(jì)算曲線的寬度,我寫了一個(gè)簡單的計(jì)算方法:

qreal WbCanvasItem::calPathWidth(QPainterPath path)
{
  qreal length = path.length();
  qreal width = PENWIDTH;

  qreal t = length/10. - 1;
  width = PENWIDTH - t;
  if(width < 3){ //最小寬度
    width = 3;
  }
  return width;
} 

PENWIDTH是一個(gè)宏定義,曲線最大寬度;

根據(jù)以上步驟,我們來看一下效果:

為了方便看效果,每條path用了不同的顏色來區(qū)分。我們可以很明顯的看到,path的寬度是不一樣的,并且每條path的連接處的寬度變化非常明顯,那么要怎么使其連接處變得平滑呢?

這時(shí)候就要用到上一篇介紹的方法進(jìn)行補(bǔ)點(diǎn)了。這里的補(bǔ)點(diǎn)比上一篇文章中說的稍微麻煩點(diǎn),需要將中間那根線條的兩頭都要補(bǔ)充點(diǎn),其原理是一樣的。

看一下示意圖:

以上紅色圈圈部分,就是補(bǔ)充的點(diǎn)。
從以上圖可以看到,path2是倒數(shù)第二條path,path3是最后一條path。

需要注意的是,圖中補(bǔ)充的兩個(gè)地方,并不是同一時(shí)間補(bǔ)充的,當(dāng)有新的path到來,只需要判斷最新的path和上一個(gè)path的寬度,從而決定是補(bǔ)充到上一個(gè)path還是當(dāng)前最新的path上。

這段話有點(diǎn)拗口,拆解一下:

假如這里path2是最后的一條path,而path1是倒數(shù)第二條,判斷出來path2寬度筆path1小,那么就在path2的路徑上補(bǔ)充點(diǎn);

再看一種情況:

同樣,這里path2是最后的一條path,而path1是倒數(shù)第二條,判斷出來path2寬度筆path1大,那么就在path1的路徑上補(bǔ)充點(diǎn);

這樣描述就很容易理解了。

OK,我們看一下補(bǔ)充點(diǎn)的代碼:

void WbCanvasItem::drawPatchPoint2(QPainter *painter, QPainterPath lastPath,
                  QPainterPath curPath,
                  qreal lastWidth, qreal curWidth)
{
  qreal tPatchLength = 100.;
  if(lastWidth < curWidth){
    tPatchLength = calPatchLength(curPath.length());

    qreal temp = (curWidth-lastWidth)/tPatchLength;
    int k = 0;

    for (qreal i = 1;i > (100-tPatchLength)/100.; i-=0.01) {
      k++;
      painter->setPen(QPen(Qt::black,curWidth-temp*k, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
      painter->drawPoint(lastPath.pointAtPercent(i));
    }
  }
  else if(lastWidth > curWidth){

    tPatchLength = calPatchLength(curPath.length());

    qreal temp = (lastWidth-curWidth)/tPatchLength;
    int k = 0;

    for (qreal i = 0;i < tPatchLength/100.; i+=0.01) {
      k++;
      painter->setPen(QPen(Qt::black,lastWidth-temp*k, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
      painter->drawPoint(curPath.pointAtPercent(i));
    }
  }
}

看一下補(bǔ)充點(diǎn)后的效果:

這里的黑色部分就是動(dòng)態(tài)補(bǔ)充上去的點(diǎn)。

好了, 整理原理分析完成,其實(shí)和前面一篇文章原理差不多,只是多了一步判斷距離然后計(jì)算線寬的過程。

到此這篇關(guān)于Qt 實(shí)現(xiàn)鋼筆畫線效果示例及詳細(xì)原理的文章就介紹到這了,更多相關(guān)Qt 鋼筆畫線內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 學(xué)習(xí) C++能帶給我們什么

    學(xué)習(xí) C++能帶給我們什么

    這篇文章主要介紹了學(xué)習(xí) C++能帶給我們什么的相關(guān)總結(jié),主要來自于前輩們,這里匯總給大家,需要的朋友可以參考下
    2016-03-03
  • C/C++中CJSON的使用(創(chuàng)建與解析JSON數(shù)據(jù))

    C/C++中CJSON的使用(創(chuàng)建與解析JSON數(shù)據(jù))

    cJSON是一個(gè)超輕巧的JSON解析器,本文主要介紹了C/C++中CJSON的使用(創(chuàng)建與解析JSON數(shù)據(jù)),具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-09-09
  • C++中cin的返回值問題

    C++中cin的返回值問題

    這篇文章主要介紹了C++中cin的返回值問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • shared_ptr線程安全性全面分析

    shared_ptr線程安全性全面分析

    正如boost文檔所宣稱的,boost為shared_ptr提供了與內(nèi)置類型同級(jí)別的線程安全性。這包括:1. 同一個(gè)shared_ptr對(duì)象可以被多線程同時(shí)讀取。2. 不同的shared_ptr對(duì)象可以被多線程同時(shí)修改成
    2013-09-09
  • C語言 指針與二維數(shù)組詳解

    C語言 指針與二維數(shù)組詳解

    本文主要介紹C語言 指針與二維數(shù)組,這里整理了詳細(xì)的資料及示例代碼,有需要的小伙伴可以參考下
    2016-08-08
  • C語言實(shí)現(xiàn)全排列算法模板的方法

    C語言實(shí)現(xiàn)全排列算法模板的方法

    這篇文章主要介紹了C語言實(shí)現(xiàn)全排列算法模板的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • C語言超詳細(xì)文件操作基礎(chǔ)下篇

    C語言超詳細(xì)文件操作基礎(chǔ)下篇

    這篇文章主要為大家詳細(xì)介紹了C語言的文件操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 在VC中隱藏控制臺(tái)程序窗口的實(shí)現(xiàn)代碼

    在VC中隱藏控制臺(tái)程序窗口的實(shí)現(xiàn)代碼

    大家都知道,當(dāng)編寫一個(gè)win32 console application時(shí),當(dāng)運(yùn)行此類程序的時(shí)候默認(rèn)情況下會(huì)有一個(gè)類似dos窗口的console窗口,但是有的時(shí)候我們只想在程序中運(yùn)行一段功能代碼,不希望顯示這個(gè)console窗口,讓代碼執(zhí)行完畢之后程序自動(dòng)退出
    2013-04-04
  • C++內(nèi)存管理介紹

    C++內(nèi)存管理介紹

    這篇文章主要介紹了C++內(nèi)存管理,C++標(biāo)準(zhǔn)委員會(huì)給我們提供了auto_ptr智能指針,后面又引入了share_ptr以及weak_ptr幫助我們正確和安全的使用指針,本文主要是介紹boost庫提供的解決方案,需要的朋友可以參考一下
    2022-01-01
  • C語言數(shù)據(jù)存儲(chǔ)歸類介紹

    C語言數(shù)據(jù)存儲(chǔ)歸類介紹

    使用編程語言進(jìn)行編程時(shí),需要用到各種變量來存儲(chǔ)各種信息。變量保留的是它所存儲(chǔ)的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個(gè)變量時(shí),就會(huì)在內(nèi)存中保留一些空間。您可能需要存儲(chǔ)各種數(shù)據(jù)類型的信息,操作系統(tǒng)會(huì)根據(jù)變量的數(shù)據(jù)類型,來分配內(nèi)存和決定在保留內(nèi)存中存儲(chǔ)什么
    2022-08-08

最新評(píng)論