C语言编写提取曲线数据程序,C语言编程高手进——贝塞尔曲线程序

答案:

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

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

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

// 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

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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值