C語(yǔ)言實(shí)現(xiàn)繪制貝塞爾曲線的函數(shù)
程序截圖
簡(jiǎn)單說(shuō)明
這個(gè)函數(shù)就是
void drawBezierCurve(COLORREF color, const unsigned int len, ...)
color 是貝塞爾曲線的顏色,len 是畫(huà)出貝塞爾曲線所需要的點(diǎn)的個(gè)數(shù),最少 1 個(gè),不要亂傳。之后的參數(shù)傳的就是畫(huà)出貝塞爾曲線要的點(diǎn),數(shù)據(jù)類型為 Vec2。
這個(gè)函數(shù)實(shí)現(xiàn)的基礎(chǔ)是參數(shù)方程,用參數(shù)方程將一條直線轉(zhuǎn)化為一個(gè)參數(shù)的方程,如:
A * x + B * y + C=0 可以轉(zhuǎn)化為 x = x0 - B * t;y = y0 + A * t,x0、y0 為直線上任意一個(gè)點(diǎn)的橫縱坐標(biāo)值,t 為未知參數(shù)。
對(duì)于一條線段,可以根據(jù)線段上兩個(gè)端點(diǎn)轉(zhuǎn)化為參數(shù)方程:
x = x0 + (x1 - x0) * t
y = y0 + (y1 - y0) * t
t ∈ [0, 1]
將這條線段分為 CURVEPIECE 份,t 從 0 到 1 一份一份地加,就能得到這條線段上均勻分布的 CURVEPIECE 個(gè)點(diǎn)。
貝塞爾曲線就是對(duì) n 個(gè)點(diǎn)連線組成的 n 條(線段上對(duì)應(yīng)份的點(diǎn))的連線的 (n - 1) 條(線段的對(duì)應(yīng)份點(diǎn))的連線的……直到最后 1 條線段上(對(duì)應(yīng)份點(diǎn)的連線)。
這個(gè)曲線的算法如果用遞歸的話可能會(huì)占用很大內(nèi)存,畢竟每一輪的點(diǎn)的值都保存下來(lái)了,我這里用循環(huán)做,空間占用只有兩輪內(nèi)點(diǎn)的值。
代碼實(shí)現(xiàn)
// 程序:畫(huà)貝塞爾曲線的函數(shù) // 編譯環(huán)境:Visual Studio 2019,EasyX_20211109 // #include <graphics.h> #include <conio.h> using namespace std; // 畫(huà)貝塞爾曲線的函數(shù),包括這個(gè) Vec2 結(jié)構(gòu)體 struct Vec2 { double x, y; }; void drawBezierCurve(COLORREF color, const unsigned int len, ...) { if (len <= 0) return; va_list list; va_start(list, len); Vec2* temp = new Vec2[len]; for (int i = 0; i < len; i++) temp[i] = va_arg(list, Vec2); va_end(list); if (len == 1) { putpixel(temp->x, temp->y, color); return; } Vec2* parent = nullptr, * child = nullptr; Vec2 lastPoint = temp[0]; setlinecolor(color); for (double LineNum = 0; LineNum < 1 + 1.0 / 100; LineNum += 1.0 / 100) { int size = len; parent = temp; while (size > 1) { child = new Vec2[size - 1]; for (int i = 0; i < size - 1; i++) { child[i].x = parent[i].x + (parent[i + 1].x - parent[i].x) * LineNum; child[i].y = parent[i].y + (parent[i + 1].y - parent[i].y) * LineNum; } if (parent != temp)delete[] parent; parent = child; size--; } line(lastPoint.x, lastPoint.y, parent->x, parent->y); lastPoint.x = parent->x; lastPoint.y = parent->y; delete[] parent; parent = nullptr; child = nullptr; } delete[] temp; } int main() { initgraph(640, 480); Vec2 a = { 100, 80 }; Vec2 b = { 540, 80 }; Vec2 c = { 540, 400 }; Vec2 d = { 100, 400 }; setlinecolor(BLUE); line(a.x, a.y, b.x, b.y); line(b.x, b.y, c.x, c.y); line(c.x, c.y, d.x, d.y); drawBezierCurve(RED, 4, a, b, c, d); _getch(); closegraph(); return 0; }
到此這篇關(guān)于C語(yǔ)言實(shí)現(xiàn)繪制貝塞爾曲線的函數(shù)的文章就介紹到這了,更多相關(guān)C語(yǔ)言繪制貝塞爾曲線內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解C語(yǔ)言結(jié)構(gòu)體,枚舉,聯(lián)合體的使用
這篇文章主要給大家介紹一下關(guān)于C語(yǔ)言中結(jié)構(gòu)體、枚舉、聯(lián)合體的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考一下2022-07-07c語(yǔ)言中malloc、realloc與calloc 的區(qū)別以及聯(lián)系
以下是對(duì)c語(yǔ)言中的malloc函數(shù),realloc函數(shù)與calloc函數(shù)的區(qū)別以及它們之間的聯(lián)系進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下2013-08-08C語(yǔ)言函數(shù)的遞歸和調(diào)用實(shí)例分析
一個(gè)函數(shù)在它的函數(shù)體內(nèi)調(diào)用它自身稱為遞歸調(diào)用。這種函數(shù)稱為遞歸函數(shù)。C語(yǔ)言允許函數(shù)的遞歸調(diào)用。在遞歸調(diào)用中,主調(diào)函數(shù)又是被調(diào)函數(shù)。執(zhí)行遞歸函數(shù)將反復(fù)調(diào)用其自身,每調(diào)用一次就進(jìn)入新的一層2013-07-07C語(yǔ)言實(shí)現(xiàn)統(tǒng)計(jì)字符串單詞數(shù)
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)統(tǒng)計(jì)字符串單詞數(shù),代碼非常的簡(jiǎn)潔,有需要的小伙伴快來(lái)參考下。2015-03-03C++實(shí)現(xiàn)模板中的非類型參數(shù)的方法
這篇文章主要介紹了C++實(shí)現(xiàn)模板中的非類型參數(shù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03c語(yǔ)言實(shí)現(xiàn)含遞歸清場(chǎng)版掃雷游戲
掃雷大家應(yīng)該都玩過(guò),這是一個(gè)十分經(jīng)典的游戲,下面這篇文章主要給大家介紹了關(guān)于c語(yǔ)言實(shí)現(xiàn)含遞歸清場(chǎng)版掃雷游戲的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-11-11