# 怎么将离散的点用平滑曲线画出来(2)

www.myexceptions.net  网友分享于：2013-01-30  浏览：1079次

C/C++ code

double lgr(double x[], double y[], int n, double t)
{
int i,j,k,m;
double z,s;
z=0.0;
if (n<1) return(z);
if (n==1) { z=y[0];return(z);}
if (n==2)
{ z=(y[0]*(t-x[1])-y[1]*(t-x[0]))/(x[0]-x[1]);
return(z);
}
i=0;
while ((x[i]<t)&&(i<n)) i=i+1;
k=i-4;
if (k<0) k=0;
m=i+3;
if (m>n-1) m=n-1;
for (i=k;i<=m;i++)
{ s=1.0;
for (j=k;j<=m;j++)
if (j!=i) s=s*(t-x[j])/(x[i]-x[j]);
z=z+s*y[i];
}
return(z);
}

void CalcDataSet(CPoint* srcDots, int nSrcSize, int i, bool bStandard_x, int& bDir, int& nFloor, int& nCeil)
{
int k;
if(bStandard_x)
{
bDir = srcDots[i].x - srcDots[i-1].x;
for(k=i;k<nSrcSize && k<=i+3;k++)
{
if(bDir * (srcDots[k].x - srcDots[k-1].x)<=0)
break;
}
if(k>nSrcSize) k=nSrcSize;
nCeil = k-1;

for(k=i-1;k>=0 && k>i-4;k--)
{
if(bDir * (srcDots[k].x - srcDots[k-1].x)<=0)
break;
}

if(k<0) k=0;
nFloor = k;
}else{

bDir = srcDots[i].y - srcDots[i-1].y;

for(k=i;k<nSrcSize && k<=i+3;k++)
{
if(bDir * (srcDots[k].y - srcDots[k-1].y)<=0)
break;
}
if(k>nSrcSize) k=nSrcSize;
nCeil = k-1;

for(k=i-1;k>=0 && k>i-4;k--)
{
if(bDir * (srcDots[k].y - srcDots[k-1].y)<=0)
break;
}

if(k<0) k=0;
nFloor = k;

}
}

void Linear_Interpolation(CPoint* srcDots, int nSrcSize, CPoint** ppDstDots, int& nDstSize)
{
double pixel_x[8];
double pixel_y[8];
nDstSize = 1;
int i,j;

for(i=1;i<nSrcSize;i++)
{
// 不包括第一个点
nDstSize += abs(srcDots[i].x-srcDots[i-1].x) + abs(srcDots[i].y-srcDots[i-1].y);
}
// 预估连续点尺寸
nDstSize = 100*nDstSize;
if(nDstSize == 0)
{
*ppDstDots = NULL;
return;
}

CPoint* pDstDots = new CPoint[nDstSize];
memset(pDstDots, 0, nDstSize*sizeof(CPoint));

(pDstDots)[0].x = srcDots[0].x;
(pDstDots)[0].y = srcDots[0].y;
CPoint lastDot(srcDots[0].x, srcDots[0].y);
j=1;
for(i=1;i<nSrcSize;i++)
{
bool bStandard_x;
int bDir_x;
int nFloor_x, nCeil_x;
int bDir_y;
int nFloor_y, nCeil_y;
int nLgrSize;

CalcDataSet(srcDots, nSrcSize, i, true, bDir_x, nFloor_x, nCeil_x);
CalcDataSet(srcDots, nSrcSize, i, false, bDir_y, nFloor_y, nCeil_y);

bStandard_x = ((nCeil_x-nFloor_x+1)>=(nCeil_y-nFloor_y+1))?true:false;

if(bStandard_x)
{
nLgrSize = nCeil_x-nFloor_x+1;
for(int k=0;k<nLgrSize;k++)
{
if(bDir_x>=0)
{
pixel_x[k] = srcDots[nFloor_x+k].x;
pixel_y[k] = srcDots[nFloor_x+k].y;
}
else
{
pixel_x[k] = srcDots[nCeil_x-k].x;
pixel_y[k] = srcDots[nCeil_x-k].y;
}
}
}
else
{
nLgrSize = nCeil_y-nFloor_y+1;
for(int k=0;k<nLgrSize;k++)
{
if(bDir_y>=0)
{
pixel_x[k] = srcDots[nFloor_y+k].x;
pixel_y[k] = srcDots[nFloor_y+k].y;
}
else
{
pixel_x[k] = srcDots[nCeil_y-k].x;
pixel_y[k] = srcDots[nCeil_y-k].y;
}
}
}

while(1)
{
double fNext_x, fNext_y;
if(bStandard_x)
{
fNext_x = lastDot.x + ((srcDots[i].x>lastDot.x)?1:-1);
fNext_y = lgr(pixel_x, pixel_y, nLgrSize, fNext_x);
}else{
fNext_y = lastDot.y + ((srcDots[i].y>lastDot.y)?1:-1);
fNext_x = lgr(pixel_y, pixel_x, nLgrSize, fNext_y);
}

if(fabs(fNext_y-lastDot.y) <= fabs(fNext_x-lastDot.x))
{
(pDstDots)[j].x = lastDot.x + ((fNext_x>lastDot.x)?1:-1);
(pDstDots)[j].y = lastDot.y;
}else if(fabs(fNext_y-lastDot.y) > fabs(fNext_x-lastDot.x))
{
(pDstDots)[j].x = lastDot.x;
(pDstDots)[j].y = lastDot.y + ((fNext_y>lastDot.y)?1:-1);
}/*else
{
(pDstDots)[i].x = lastDot.x + ((srcDots[i].x>lastDot.x)?1:-1);
(pDstDots)[i].y = lastDot.y + ((srcDots[i].y>lastDot.y)?1:-1);
}*/

lastDot.x = (pDstDots)[j].x;
lastDot.y = (pDstDots)[j].y;
j++;

char szLog[512];
sprintf(szLog, "(%4d,%4d)-(%f, %f)\t(%4d,%4d)-(%4d,%4d)",lastDot.x, lastDot.y, fNext_x, fNext_y, srcDots[i-1].x, srcDots[i-1].y,
srcDots[i].x, srcDots[i].y);
OutputDebugString(szLog);

bool bBreak = false;
if(bStandard_x)
{

if(lastDot.x == srcDots[i].x)
{
bBreak = true;
}

}else
{

if(lastDot.y == srcDots[i].y)
{
bBreak = true;
}

}

if(bBreak)
break;

}

}
nDstSize = j;
*ppDstDots = new CPoint[nDstSize];
for(int i=0;i<nDstSize;i++)
{
(*ppDstDots)[i].SetPoint(pDstDots[i].x, pDstDots[i].y);
}
delete []pDstDots;
}