貝賽爾曲線的每一個頂點都有兩個控制點,用於控制在該頂點兩側的曲線的弧度。所以本函式的頂點數組的記錄方式是:控制點+頂點+控制點+控制點+頂點+控制點+……。所以兩個頂點之間的曲線是由兩個頂點以及兩個頂點之間的控制點來決定的。
==主函式PolyBezierToPolys==
【主要類型申明】
typedef CArray<CPoint,CPoint> CPtArray;//點動態數組類型
【參數說明】
bezierPts[in]---貝賽爾曲線頂點和控制點數組
bClose[in]------是否封閉的貝賽爾曲線
polyPt[out]-----拆分後的多邊形點數組
precision[in]---拆分精度
bool PolyBezierToPolys(CPtArray &bezierPts,
bool bClose,CPtArray &polyPt,int precision)
{
polyPt.RemoveAll();
CPtArray apt;
int i,count = bezierPts.GetSize();
//從1開始,是因為第一個是控制點,如果曲線不封閉,那么第一個控制點是沒有用的。
//每一段貝賽爾曲線由相鄰的兩個頂點和之間的兩個控制點決定,所以頻率為3(後一個頂點在下一組中還要使用)
for(i=1;i<count-2;i+=3){
BezierToPoly(&bezierPts,apt,precision); //拆分每一段
polyPt.Append(apt);//拆分完成,加入數組
}
//如果是封閉曲線,那么需要將最後一個頂點和第一個頂點以及最後一個控制點以及第一個控制點組成一組進行拆分
if(bClose){
CPoint ptBuffer[4];
ptBuffer[0] = bezierPts[count-2];
ptBuffer[1] = bezierPts[count-1];
ptBuffer[2] = bezierPts[0];
ptBuffer[3] = bezierPts[1];
BezierToPoly(&ptBuffer[0], apt,precision);
polyPt.Append(apt);
}
count = polyPt.GetSize();
i=0;
//過濾相鄰的值相等的點(由於精度和誤差,可能會有一些坐標值相同的相鄰拆分點)
while(i<count-1){
if(polyPt ==polyPt[i+1]){
polyPt.RemoveAt(i+1);
count--;
continue;
}
i++;
}
return true;
}
//拆分貝賽爾曲線
bool InciseBezier(CPoint *pSrcPt, CPoint *pDstPt)
{
CPoint buffer[3][3];
int i;
for(i=0;i<3;i++){
buffer[0] = pSrcPt + pSrcPt[i+1];
buffer[0].x /=2;
buffer[0].y /=2;
}
for(i=0;i<2;i++){
buffer[1] = buffer[0] + buffer[0][i+1];
buffer[1].x /=2;
buffer[1].y /=2;
}
buffer[2][0] = buffer[1][0] + buffer[1][1];
buffer[2][0].x /=2;
buffer[2][0].y /=2;
pDstPt[0]=pSrcPt[0];
pDstPt[1]=buffer[0][0];
pDstPt[2]=buffer[1][0];
pDstPt[3]=buffer[2][0];
pDstPt[4]=buffer[1][1];
pDstPt[5]=buffer[0][2];
pDstPt[6]=pSrcPt[3];
return true;
}
//拆分一組貝賽爾曲線段
bool BezierToPoly(CPoint *pSrcPts,CPtArray &polyPt,int precision)
{
polyPt.RemoveAll();
polyPt.SetSize(4);
polyPt[0] = pSrcPts[0];
polyPt[1] = pSrcPts[1];
polyPt[2] = pSrcPts[2];
polyPt[3] = pSrcPts[3];
CPoint ptBuffer[7];
int i,j,count =4;
bool bExit;
while(true){
bExit = true;
for(i=0;i<count-1;i+=3){
// if(GetBezierGap(&polyPt)>precision){
if(!EndBezierCut(&polyPt, precision)){
bExit = false;
InciseBezier(&polyPt, ptBuffer);
polyPt.RemoveAt(i+1,2);
polyPt.InsertAt(i+1,ptBuffer[1],5);
for(j=0;j<4;j++)
polyPt[i+2+j] = ptBuffer[2+j];
i += 3;
count += 3;
}
}
if(bExit)
break;
}
count = polyPt.GetSize();
i=0;
while(i<count-1){
if(polyPt ==polyPt[i+1]){
polyPt.RemoveAt(i+1);
count--;
continue;
}
i++;
}
return true;
}
/計算貝賽爾曲線兩個頂點的縱向和橫向的最大距離
int GetBezierGap(CPoint *p)
{
int gap = 0;
for(int i=1;i<4;i++){
if(abs(p.x-p[i-1].x)>gap)
gap=abs(p.x-p[i-1].x);
if(abs(p.y-p[i-1].y)>gap)
gap=abs(p.y-p[i-1].y);
}
return gap;
}
//判斷是否可以終止更精細得拆分
bool EndBezierCut(CPoint *ptBezier, int nExtent)
{
double C,dx,dy,delt,delt1,delt2;
if (nExtent<2)
nExtent = 2;
dx = (double)(ptBezier[3].x - ptBezier[0].x);
dy = (double)(ptBezier[3].y - ptBezier[0].y);
C = dx * ptBezier[0].y - dy * ptBezier[0].x;
delt = (double)nExtent*nExtent*(dy*dy+dx*dx);
delt1 = dy * ptBezier[1].x - dx * ptBezier[1].y + C;
delt2 = dy * ptBezier[2].x - dx * ptBezier[2].y + C;
delt1 = delt1 * delt1;
delt2 = delt2 * delt2;
if (delt1 > delt || delt2 > delt)
return FALSE;
else
return TRUE;
}
相關詞條
-
計算機圖形學算法與套用
計算機圖形學算法與套用全面介紹了計算機圖形學的基本概念、原理和算法,是根據作者長期從事計算機圖形學的教學經驗和科研成果,並參考了國內外同類教材編寫而成,...
圖書信息: 內容簡介: 章節目錄: -
數值計算方法和算法
《數值計算方法和算法》是2000年科學出版社出版的一本圖書。本書介紹各種常用的數值計算方法,簡述計算方法的計算對象、計算原理和計算步驟,給出部分數值方法...
圖書信息 內容簡介 目錄 -
3D計算機圖形學(OpenGL版)
HSL色彩的表達。第7章貝塞爾曲線,三階和通用階次的貝塞爾曲線;De Casteljau 方法;細分;分段貝塞爾曲線;Hermite 多項式;貝塞爾曲面片;OpenGL中的貝塞爾曲線;有理貝塞爾曲線;圓錐曲線段,階次...
圖書信息 圖書簡介 圖書前言 圖書目錄 -
量子物理學中的常用算法與程式
4.2疊代法 4.3二分法 5.2疊代法
圖書相信 內容簡介 目錄 -
《上帝擲骰子嗎》
古格列爾莫•馬可尼(Guglielmo Marconi),與此同時俄國...
《上帝擲骰子嗎》 序 第一章 黃金時代 第二章 烏雲 第三章 火流星 -
計算機圖形學實用技術(第3版)
CLine452.4.3 貝塞爾曲線類CBezier462.4.4 矩形類...增加了Bezier曲線的de Casteljau算法及偽碼和Bezier...曲線示意圖,增設deboor算法及偽代碼。本書由陳元琰主筆,張睿哲參與...
圖書簡介 圖書信息 前言 目錄 -
數學物理方法[郭玉翠主編書籍]
、散度與旋度在正交曲線坐標系中的表達式1.2.1直角坐標系中的“三度”及Hamilton運算元1.2.2正交曲線坐標系中的“三度”1.2.3“三度”的運算公式1.3正交曲線坐標系中的Laplace算符、Green第一和...
圖書信息 清華版 北理工版 西科大版 同名教材 -
伯恩斯坦多項式
(近似理論)。 [1] 貝塞爾曲線貝塞爾曲線(Bézier curve...曲線的。貝塞爾曲線是計算機圖形學中相當重要的參數曲線,在一些比較成熟的點陣圖軟體中也有貝塞爾曲線工具,如PhotoShop等。在Flash4中...
人物簡介 貝塞爾曲線 詳細定義 常用性質 -
數學年譜
了乘法表,其中使用著六十進位制的算法。 公元前1900~前1600,古埃及...、分數計算法。並已有三角形及圓的面積、正方角錐體、錐台體積的度量法...。古希臘的塞馬力達斯開始世界簡單方程組。 公元前335年,古希臘的歐...