我需要开发一种算法,该算法以非线性的方式连接点,即使用 平滑曲线 下图:
问题是我无法找到最佳解决方案,无论是使用Bezier Curves,Polimonial Interpolation,Curve Adjustment还是其他方式。
简而言之,我需要一个公式,根据上图对点进行插值,从而在一个坐标和另一个坐标之间生成N个中间点。
在上图中,第一个坐标(c1)为(x = 1,y = 220),第二个坐标(c2)为(x = 2,y = 40)。
因此,如果我想在c1和c2之间创建4个中间坐标,则必须得到一个由4个元素组成的数组(x,y),如下所示:
[1.2, 180], [1.4, 140], [1.6, 120], [1.8, 80]
有人有什么想法吗?
答案 0 :(得分:3)
我认为任何Piecewise curve interpolation都应该这样做。下面是一个 C ++ 示例:
//---------------------------------------------------------------------------
const int n=7; // points
const int n2=n+n;
float pnt[n2]= // points x,y ...
{
1.0, 220.0,
2.0, 40.0,
3.0,-130.0,
4.0,-170.0,
5.0,- 40.0,
6.0, 90.0,
7.0, 110.0,
};
//---------------------------------------------------------------------------
void getpnt(float *p,float t) // t = <0,n-1>
{
int i,ii;
float *p0,*p1,*p2,*p3,a0,a1,a2,a3,d1,d2,tt,ttt;
// handle t out of range
if (t<= 0.0f){ p[0]=pnt[0]; p[1]=pnt[1]; return; }
if (t>=float(n-1)){ p[0]=pnt[n2-2]; p[1]=pnt[n2-1]; return; }
// select patch
i=floor(t); // start point of patch
t-=i; // parameter <0,1>
i<<=1; tt=t*t; ttt=tt*t;
// control points
ii=i-2; if (ii<0) ii=0; if (ii>=n2) ii=n2-2; p0=pnt+ii;
ii=i ; if (ii<0) ii=0; if (ii>=n2) ii=n2-2; p1=pnt+ii;
ii=i+2; if (ii<0) ii=0; if (ii>=n2) ii=n2-2; p2=pnt+ii;
ii=i+4; if (ii<0) ii=0; if (ii>=n2) ii=n2-2; p3=pnt+ii;
// loop all dimensions
for (i=0;i<2;i++)
{
// compute polynomial coeficients
d1=0.5*(p2[i]-p0[i]);
d2=0.5*(p3[i]-p1[i]);
a0=p1[i];
a1=d1;
a2=(3.0*(p2[i]-p1[i]))-(2.0*d1)-d2;
a3=d1+d2+(2.0*(-p2[i]+p1[i]));
// compute point coordinate
p[i]=a0+(a1*t)+(a2*tt)+(a3*ttt);
}
}
//---------------------------------------------------------------------------
void gl_draw()
{
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
// set 2D view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(1.0/5.0,1.0/500.0,1.0);
glTranslatef(-4.0,0.0,0.0);
// render lines
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINE_STRIP);
float p[2],t;
for (t=0.0;t<=float(n-1);t+=0.1f)
{
getpnt(p,t);
glVertex2fv(p);
}
glEnd();
// render points
glPointSize(4.0);
glColor3f(0.0,0.0,1.0);
glBegin(GL_POINTS);
for (int i=0;i<n2;i+=2) glVertex2fv(pnt+i);
glEnd();
glPointSize(1.0);
glFinish();
SwapBuffers(hdc);
}
//---------------------------------------------------------------------------
这里预览:
您可以看到它很简单,您只需要n
个控制点pnt
(我从图形中提取)并进行插值... getpnt
函数将计算参数t=<0,n-1>
处理的曲线。在内部,它仅选择要使用的三次面片并将其计算为单次三次曲线。在gl_draw
中,您可以了解如何使用它来获取介于两者之间的点。
由于您的控制点均匀地分布在x
轴上:
x = <1,7>
t = <0,6>
我可以写:
x = t+1
t = x-1
所以您也可以为任何x
计算任意点...
形状不完全匹配您的图形,因为选定的控制点不是正确的控制点。任何局部最小值/最大值应作为控制点,有时也更安全地使用非弯曲点。曲线的起点和终点形状暗示了隐藏的起点和终点控制点,该点未在图中显示。您可以使用任意数量的点,但是要注意,如果破坏x均匀分布,那么您将失去直接从t
计算x
的能力!
由于我们不知道图形是如何创建的,所以只能猜测...