分享
 
 
 

贝赛尔曲线的拆分算法

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

贝赛尔曲线的拆分是指将贝赛尔曲线分解成逼近的多边形。可以用来判断贝赛尔曲线的选中,以及显示贝赛尔曲线的旋转效果等。

贝赛尔曲线简单介绍:

贝赛尔曲线的每一个顶点都有两个控制点,用于控制在该顶点两侧的曲线的弧度。所以本函数的顶点数组的记录方式是:控制点+顶点+控制点+控制点+顶点+控制点+……。所以两个顶点之间的曲线是由两个顶点以及两个顶点之间的控制点来决定的。

===主函数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[i],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[i] ==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][i] = pSrcPt[i] + pSrcPt[i+1];

buffer[0][i].x /=2;

buffer[0][i].y /=2;

}

for(i=0;i<2;i++){

buffer[1][i] = buffer[0][i] + buffer[0][i+1];

buffer[1][i].x /=2;

buffer[1][i].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[i])>precision){

if(!EndBezierCut(&polyPt[i], precision)){

bExit = false;

InciseBezier(&polyPt[i], 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[i] ==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[i].x-p[i-1].x)>gap)

gap=abs(p[i].x-p[i-1].x);

if(abs(p[i].y-p[i-1].y)>gap)

gap=abs(p[i].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;

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有