顺畅连接圆心

我试图沿着中心画一条穿过管子内部的路径。 我必须处理的数据是圆圈的中心点,描述管道中每个转弯的开始和结束时的管道。

通过管道的直线段绘制路径是微不足道的,但我不确定如何接近弯道。 两个圆之间的任何转弯应该是恒定的半径。 因此,我可以访问此圆上的两个点,以及该点处圆圈线的方向。

有谁知道我将如何计算这个圈子的其余部分?

编辑:

附上了照片般逼真的管道素描。

这就像我在管道中!

因此,假装曲线不会像地狱那样摇摆不定,蓝色线条表示圆圈,红色表示中心点,绿色表示穿过中心的路径。

  1. 澄清

    管子到处都有相同的圆形直径,所以不会因弯曲而产生变形! 输入是2个端点(管中心) P0,P1和2个矢量(管的正常/方向) N0,N1

    弯管

  2. 使用插值立方体,例如这一个

     p(t)=a0+a1*t+a2*t*t+a3*t*t*t t=<0,1.0> 

    所以写出已知数据的方程式,求解你需要的每个轴的a0,a1,a2,a3系数(2D: x,y )然后你可以得到沿弯曲侧任意点的中心点及其法线,这就是什么你需要。

    现在一些通用方程式:

     p(t)=a0+a1*t+ a2*t*t+ a3*t*t*t // circle center position n(t)= a1 +2.0*a2*t +3.0*a3*t*t // circle orientation 
    • p,n,a0,a1,a2,a3是矢量!!!
    • t是标量

    现在添加已知数据

     I. t=0 -> p(0)=P0 P0=a0 a0=P0 II. t=0 -> n(0)=N0 N0=a1 a1=N0 III. t=1 -> p(1)=P1 P1=a0+a1+a2+a3 P1=P0+N0+a2+a3 a2=P1-P0-N0-a3 IV. t=1 -> n(1)=N1 N1=a1+2.0*a2+3.0*a3 N1=N0+2.0*(P1-P0-N0-a3)+3.0*a3 a3=N1+N0-2.0*(P1-P0) III. a2=P1-P0-N0-(N1+N0-2.0*(P1-P0)) a2=P1-P0-N0-N1-N0+2.0*(P1-P0) a2=P1-P0-N1+2.0*(P1-P0-N0) a2=3.0*(P1-P0)-N1-2.0*N0 

    因此,如果我没有犯任何愚蠢的错误,那么系数是:

     a0=P0 a1=N0 a2=3.0*(P1-P0)-N1-2.0*N0 a3=N1+N0-2.0*(P1-P0) 

    所以现在只需将通用方程式编码为某个函数,输入参数为t ,输出p(t)n(t)和/或渲染圆或管段,并将其调用为for循环,例如:

     for (t=0.0;t<=1.0;t+=0.1) f(t); 

[edit1] C ++实现

 //--------------------------------------------------------------------------- void glCircle3D(double *pos,double *nor,double r,bool _fill) { int i,n=36; double a,da=divide(pi2,n),p[3],dp[3],x[3],y[3]; if (fabs(nor[0]-nor[1])>1e-6) vector_ld(x,nor[1],nor[0],nor[2]); else if (fabs(nor[0]-nor[2])>1e-6) vector_ld(x,nor[2],nor[1],nor[0]); else if (fabs(nor[1]-nor[2])>1e-6) vector_ld(x,nor[0],nor[2],nor[1]); else vector_ld(x,1.0,0.0,0.0); vector_mul(x,x,nor); vector_mul(y,x,nor); vector_len(x,x,r); vector_len(y,y,r); if (_fill) { glBegin(GL_TRIANGLE_FAN); glVertex3dv(pos); } else glBegin(GL_LINE_STRIP); for (a=0.0,i=0;i<=n;i++,a+=da) { vector_mul(dp,x,cos(a)); vector_add(p,pos,dp); vector_mul(dp,y,sin(a)); vector_add(p,p ,dp); glVertex3dv(p); } glEnd(); } //--------------------------------------------------------------------------- void tube(double *P0,double *N0,double *P1,double *N1,double R) { int i; double a0[3],a1[3],a2[3],a3[3],p[3],n[3],t,tt,ttt; // compute coefficients for (i=0;i<3;i++) { a0[i]=P0[i]; a1[i]=N0[i]; a2[i]=(3.0*(P1[i]-P0[i]))-N1[i]-(2.0*N0[i]); a3[i]=N1[i]+N0[i]-2.0*(P1[i]-P0[i]); } // step through curve from t=0 to t=1 for (t=0.0;t<=1.0;t+=0.02) { tt=t*t; ttt=tt*t; // compute circle position and orientation for (i=0;i<3;i++) { p[i]=a0[i]+(a1[i]*t)+(a2[i]*tt)+(a3[i]*ttt); n[i]=a1[i]+(2.0*a2[i]*t)+(3.0*a3[i]*tt); } // render it glCircle3D(p,n,R,false); } } //--------------------------------------------------------------------------- void test() { // tube parameters double P0[3]={-1.0, 0.0, 0.0},N0[3]={+1.0,-1.0, 0.0},p[3]; double P1[3]={+1.0,+1.0, 0.0},N1[3]={ 0.0,+1.0, 0.0}; // just normalize normals to size 3.1415... vector_len(N0,N0,M_PI); vector_len(N1,N1,M_PI); // draw normals to visula confirmation of tube direction glBegin(GL_LINES); glColor3f(0.0,0.0,1.0); vector_add(p,P0,N0); glVertex3dv(P0); glVertex3dv(p); glColor3f(0.0,0.0,1.0); vector_add(p,P1,N1); glVertex3dv(P1); glVertex3dv(p); glEnd(); // render tube glColor3f(1.0,1.0,1.0); tube(P0,N0,P1,N1,0.2); } //--------------------------------------------------------------------------- 

在视觉上,当法线的大小为M_PI (3.1415...)时,最好看看它是如何查找上面的代码:

管道C ++

我的代码使用了我的矢量库,所以你只需要编写如下函数:

 vector_ld(a,x,y,z); //a[]={ x,y,z } vector_mul(a,b,c); //a[]=b[] xc[] vector_mul(a,b,c); //a[]=b[] * c vector_add(a,b,c); //a[]=b[] + c[] vector_sub(a,b,c); //a[]=b[] - c[] vector_len(a,b,c); //a[]=b[]* c / |b[]| 

这很容易(希望我不要忘记复制一些东西......)......