最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

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

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

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

實現(xiàn)原理

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

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

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

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

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

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

計算曲線的寬度,我寫了一個簡單的計算方法:

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是一個宏定義,曲線最大寬度;

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

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

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

看一下示意圖:

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

需要注意的是,圖中補充的兩個地方,并不是同一時間補充的,當有新的path到來,只需要判斷最新的path和上一個path的寬度,從而決定是補充到上一個path還是當前最新的path上。

這段話有點拗口,拆解一下:

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

再看一種情況:

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

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

OK,我們看一下補充點的代碼:

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

看一下補充點后的效果:

這里的黑色部分就是動態(tài)補充上去的點。

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

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

相關文章

  • 簡單了解C++語言中的二元運算符和賦值運算符

    簡單了解C++語言中的二元運算符和賦值運算符

    這篇文章主要介紹了C++語言中的二元運算符和賦值運算符,文中列出了可重載的運算符列表,需要的朋友可以參考下
    2016-01-01
  • C語言main()函數(shù)的參數(shù)問題詳解

    C語言main()函數(shù)的參數(shù)問題詳解

    這篇文章主要為大家詳細介紹了C語言main()函數(shù)的參數(shù)問題,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • VC++實現(xiàn)CStdioFile寫入及讀取文件并自動換行的方法

    VC++實現(xiàn)CStdioFile寫入及讀取文件并自動換行的方法

    這篇文章主要介紹了VC++實現(xiàn)CStdioFile寫入及讀取文件并自動換行的方法,很實用的功能,需要的朋友可以參考下
    2014-08-08
  • C語言實現(xiàn)與電腦玩剪刀石頭布游戲

    C語言實現(xiàn)與電腦玩剪刀石頭布游戲

    這篇文章主要為大家詳細介紹了如何通過C語言實現(xiàn)和電腦玩剪刀石頭布游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-11-11
  • 基于Matlab實現(xiàn)中國象棋的示例代碼

    基于Matlab實現(xiàn)中國象棋的示例代碼

    中國象棋是起源于中國的一種棋,屬于二人對抗性游戲的一種,在中國有著悠久的歷史。由于用具簡單,趣味性強,成為流行極為廣泛的棋藝活動。本文將利用Matlab實現(xiàn)這一游戲,需要的可以參考一下
    2022-02-02
  • C語言實現(xiàn)職工管理系統(tǒng)

    C語言實現(xiàn)職工管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)職工管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • c++元編程模板函數(shù)重載匹配規(guī)則示例詳解

    c++元編程模板函數(shù)重載匹配規(guī)則示例詳解

    這篇文章主要為大家介紹了c++元編程模板函數(shù)重載匹配規(guī)則示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • Java?C++題解?leetcode第k個數(shù)實例

    Java?C++題解?leetcode第k個數(shù)實例

    這篇文章主要為大家介紹了Java?C++題解?leetcode第k個數(shù)實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • C++深入講解類與對象之OOP面向?qū)ο缶幊膛c封裝

    C++深入講解類與對象之OOP面向?qū)ο缶幊膛c封裝

    學習過C語言的小伙伴知道:C語言是面向過程的,關注的是過程,分析出求解問題的步驟,通過函數(shù)調(diào)用逐步解決問題,接下來讓我們詳細的了解
    2022-05-05
  • 教你分辨C++堆與棧的區(qū)別

    教你分辨C++堆與棧的區(qū)別

    堆與棧的區(qū)別有:1、棧由系統(tǒng)自動分配,而堆是人為申請開辟;2、棧獲得的空間較小,而堆獲得的空間較大;3、棧由系統(tǒng)自動分配,速度較快,而堆一般速度比較慢;4、棧是連續(xù)的空間,而堆是不連續(xù)的空間
    2021-06-06

最新評論

遵义市| 贵港市| 肇庆市| 陆河县| 广德县| 宣化县| 扶绥县| 武川县| 万州区| 临颍县| 沙河市| 光山县| 吉木乃县| 城市| 莆田市| 石阡县| 柯坪县| 尉氏县| 达孜县| 于田县| 高安市| 中卫市| 盘山县| 遂昌县| 长顺县| 扎鲁特旗| 西华县| 东安县| 凤庆县| 乌苏市| 远安县| 南阳市| 新干县| 杭州市| 越西县| 阳东县| 西畴县| 岑溪市| 仁化县| 团风县| 太湖县|