WPF如何繪制光滑連續(xù)貝塞爾曲線示例代碼
1.需求
WPF本身沒有直接把點集合繪制成曲線的函數(shù)。可以通過貝塞爾曲線函數(shù)來繪制?! ?/p>
貝茲曲線由線段與節(jié)點組成,節(jié)點是可拖動的支點,線段像可伸縮的皮筋,我們在繪圖工具上看到的鋼筆工具就是來做這種矢量曲線的。當(dāng)然在一些比較成熟的位圖軟件中也有貝塞爾曲線工具,如PhotoShop等。
貝塞爾曲線類是:BezierSegment,三次貝塞爾曲線,通過兩個控制點來控制開始和結(jié)束方向。
QuadraticBezierSegment,二次貝塞爾,通過一個控制點來控制彎曲方向。
本文使用的是三次。
圖片來源維基百科
2.思路
大值思路是根據(jù)當(dāng)前點,前一個點,后一個點,再后一個點。共四個點,來生成一條三次貝塞爾曲線。

曲線需要(開始點,結(jié)束點,控制點1,控制點2),圖中標(biāo)識的兩個紅色點即是控制點。
代碼主要是計算兩個紅色的控制點。
先計算相鄰點的中點【橙色】。
再將中點的連線平移到相鄰的位置【藍(lán)色點】,取得虛線,得到虛線的端點【紅色】。
紅色,即為控制點。
3.主要代碼
/// <summary>
/// 獲得貝塞爾曲線
/// </summary>
/// <param name="currentPt">當(dāng)前點</param>
/// <param name="lastPt">上一個點</param>
/// <param name="nextPt1">下一個點1</param>
/// <param name="nextPt2">下一個點2</param>
/// <returns></returns>
private BezierSegment GetBezierSegment(Point currentPt, Point lastPt, Point nextPt1, Point nextPt2)
{
//計算中點
var lastC = GetCenterPoint(lastPt, currentPt);
var nextC1 = GetCenterPoint(currentPt, nextPt1); //貝塞爾控制點
var nextC2 = GetCenterPoint(nextPt1, nextPt2);
//計算相鄰中點連線跟目的點的垂足
//效果并不算太好,因為可能點在兩個線上或者線的延長線上,計算會有誤差
//所以就直接使用中點平移方法。
//var C1 = GetFootPoint(lastC, nextC1, currentPt);
//var C2 = GetFootPoint(nextC1, nextC2, nextPt1);
//計算“相鄰中點”的中點
var c1 = GetCenterPoint(lastC, nextC1);
var c2 = GetCenterPoint(nextC1, nextC2);
//計算【"中點"的中點】需要的點位移
var controlPtOffset1 = currentPt - c1;
var controlPtOffset2 = nextPt1 - c2;
//移動控制點
var controlPt1 = nextC1 + controlPtOffset1;
var controlPt2 = nextC1 + controlPtOffset2;
//如果覺得曲線幅度太大,可以將控制點向當(dāng)前點靠近一定的系數(shù)。
controlPt1 = controlPt1 + 0 * (currentPt - controlPt1);
controlPt2 = controlPt2 + 0 * (nextPt1 - controlPt2);
var bzs = new BezierSegment(controlPt1, controlPt2, nextPt1, true);
return bzs;
}
效果圖如下:
4.源碼下載
http://xiazai.jb51.net/201804/yuanma/WPF-BezierSegment(jb51.net).rar
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
C#實現(xiàn)Winform鼠標(biāo)拖動窗口大小時設(shè)定窗口最小尺寸的方法
這篇文章主要介紹了C#實現(xiàn)Winform鼠標(biāo)拖動窗口大小時設(shè)定窗口最小尺寸的方法,涉及WinForm改變窗口大小時動態(tài)判斷當(dāng)前窗口尺寸的相關(guān)技巧,非常簡單實用,需要的朋友可以參考下2015-11-11
C#使用post發(fā)送和接收數(shù)據(jù)的方法
這篇文章主要介紹了C#使用post發(fā)送和接收數(shù)據(jù)的方法,涉及C#使用post收發(fā)數(shù)據(jù)的相關(guān)技巧,非常具有實用價值,需要的朋友可以參考下2015-04-04
C# .Net實現(xiàn)灰度圖和HeatMap熱力圖winform(進(jìn)階)
本文主要介紹了C# .NET實現(xiàn)簡易灰度圖和酷炫HeatMap熱力圖winform,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12
淺談C#2.0泛型中的變化:default關(guān)鍵字
下面就詳細(xì)的說明一下。之所以會用到default關(guān)鍵字,是因為需要在不知道類型參數(shù)為值類型還是引用類型的情況下,為對象實例賦初值2013-09-09
C#中接口的顯式實現(xiàn)與隱式實現(xiàn)及其相關(guān)應(yīng)用案例詳解
最近在學(xué)習(xí)演化一款游戲項目框架時候,框架作者巧妙使用接口中方法的顯式實現(xiàn)來變相對接口中方法進(jìn)行“密封”,增加實現(xiàn)接口的類訪問方法的“成本”,這篇文章主要介紹了C#中接口的顯式實現(xiàn)與隱式實現(xiàn)及其相關(guān)應(yīng)用案例,需要的朋友可以參考下2024-05-05
C# Dynamic關(guān)鍵字之:dynamic為什么比反射快的詳解
本篇文章是對C#中dynamic為什么比反射快進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05

