Плавно соединяющие центры

Я пытаюсь проложить путь через внутреннюю часть трубки, вдоль центра. Данные, с которыми я должен работать, – это центральные точки кругов, описывающих трубку в начале и в конце каждого поворота трубы.

Проложить путь через прямые участки трубы тривиально, но я не уверен, как подойти к изгибам. Любой поворот между двумя кругами должен иметь постоянный радиус. Поэтому у меня есть доступ к двум точкам на этом круге и направлению линии окружности в этой точке.

Кто-нибудь знает, как я буду вычислять остальную часть круга из этого?

Редактировать:

Прикрепленный фотореалистичный эскиз трубы.

Это как я в трубке!

Так что притворяйтесь, что кривая не является шаткой, как черт, синие линии указывают круг, красные точки центра и зеленый путь по центру.

  1. осветление

    труба имеет одинаковый круглый диаметр везде, поэтому никаких искажений из-за изгиба нет! вход 2 точки конечных точек (центры трубки) P0,P1 и 2 вектора (нормальное / направление трубки) N0,N1

    изгиб трубы

  2. Решение

    Используйте Interpolation кубический, например, этот

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

    поэтому напишите уравнения для известных данных, a0,a1,a2,a3 коэффициенты 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 (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); } //--------------------------------------------------------------------------- 1 //--------------------------------------------------------------------------- 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); } //--------------------------------------------------------------------------- 1 //--------------------------------------------------------------------------- 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[]| 

что легко (надеюсь, я не забыл что-то скопировать ...) ...

  • Матричная обратная точность
  • Математика с фиксированной точкой в ​​c #?
  • Создайте случайную точку внутри круга (равномерно)
  • Головоломка: найдите самый большой прямоугольник (проблема с максимальным прямоугольником)
  • Присоединение полиномов к данным
  • Простой алгоритм пересечения многоугольников
  • Подписанный угол между двумя 3D-векторами с одинаковым началом в одной плоскости
  • Почему десятичные числа не могут быть представлены точно в двоичном формате?
  • Математически вычислить простой графический конвейер
  • Вычислить вторую точку, зная начальную точку и расстояние
  • Является ли Big log (logn) базой базы?
  • Давайте будем гением компьютера.