1. 程式人生 > >問題六十一:三次b樣條(b-spline)曲線的控制點和曲線形狀的對應——以迴旋體的“基本曲線”為例

問題六十一:三次b樣條(b-spline)曲線的控制點和曲線形狀的對應——以迴旋體的“基本曲線”為例

在這一章節,我們以其中一段曲線段為例,改變其對應的控制點,看看曲線段形狀的改變,同時也看看對應的迴旋體圖形的改變。

控制點座標如下圖:


“問題六十”中的“基本曲線”的控制點對應如上ABCDEF六個點(其中A點在1位置)。對應輸出的迴旋體圖形如下(再次貼出來):


說明一下:

1,由於我們接下來測試時的lookfrom座標和“問題六十”中的座標是有差異的,所以,輸出的圖形立體呈現是有差異的。

2,接下來,我們圖片中的曲線段是從迴旋體上切下來的,會得到兩條關於y軸對稱的曲線段,實際的“基本曲線”中的曲線段對應其中的一條。

我們知道如上回旋體的“基本曲線”是有三段三次b-spline曲線段拼接而成,分別對應的控制點為ABCD、BCDE、CDEF。

我們接下來要測試的是控制點ABCD對應的曲線段。

測試方式:BCD的位置保持不變,A點的位置依次如下改變(12,7,6,2,1,3,5,4,8,9,10,11),然後對比這12中情況的曲線段的變化情況和對應迴旋體的變化情況。

//12
        vec3 ctrl_points[6] = {vec3(-2.0, -3.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//7
        vec3 ctrl_points[6] = {vec3(-4.0,  0.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//6
        vec3 ctrl_points[6] = {vec3(-4.0,  2.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//2
        vec3 ctrl_points[6] = {vec3(-4.0,  5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//1
        vec3 ctrl_points[6] = {vec3(-1.0,  5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//3
        vec3 ctrl_points[6] = {vec3( 2.0,  5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//5
        vec3 ctrl_points[6] = {vec3( 2.0,  7.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//4
        vec3 ctrl_points[6] = {vec3( 4.0,  5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//8--discover some problems
        vec3 ctrl_points[6] = {vec3( 4.0,  4.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//9
        vec3 ctrl_points[6] = {vec3( 4.0,  2.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//10
        vec3 ctrl_points[6] = {vec3( 4.0,  0.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};
//11
        vec3 ctrl_points[6] = {vec3( 3.0, -5.0,  0.0), vec3( 2.0,  4.0,  0.0),
                               vec3( 2.0,  1.0,  0.0), vec3(-0.5,  1.0,  0.0),
                               vec3( 1.5, -3.0,  0.0), vec3( 3.0,  0.0,  0.0)};



接下來,貼一份A在1位置的完整拆解圖形:

=++

=++

最後,說一下,“曲線段”是怎麼從迴旋體中切出來的呢?

只需要對“一元六次方程”的根對應的z座標的範圍加以限制即可。對應修改的程式碼:

                roots_equation_6th(ss6, 0, 1, tol, roots);
                for (int j=1; j<(int(roots[0])+1); j++) {
                    yyv = matrix_c_v[0][i]+matrix_c_v[1][i]*roots[j]+matrix_c_v[2][i]*roots[j]*roots[j]+matrix_c_v[3][i]*roots[j]*roots[j]*roots[j];
                    roots_t[num_roots_t+1][0] = (yyv-yy0)/yyd;
                    rec.t = roots_t[num_roots_t+1][0];
                    rec.p = r.point_at_parameter(rec.t);
                    if (fabs(rec.p.z())<0.5) {
                        roots_t[num_roots_t+1][1] = i;
                        roots_t[num_roots_t+1][2] = roots[j];
                        num_roots_t ++;
                    }
                }
            }
            roots_t[0][0] = float(num_roots_t);