00001
00015 #ifndef _SUBDIVISIONMANIFOLD_H
00016 #define _SUBDIVISIONMANIFOLD_H
00017
00018
00019 #include <TensorManifold.H>
00020 #include <arglst.H>
00021 #include <GL/gl.h>
00022 #include <xstl.H>
00023
00024
00025 namespace xchen
00026 {
00028 template<int dims = 2, int sp_dims = 3>
00029 class SubdivisionManifold : public TensorManifold<dims, sp_dims>
00030 {
00031 int len[dims];
00032 int left_ec[dims], right_ec[dims];
00033 enum {open_end, floating_end, periodic_end};
00034
00035 def_type_name_for_tensor_manifold(dims, sp_dims);
00036
00037 public:
00038 SubdivisionManifold(int deg1, ...);
00039 SubdivisionManifold(int* degsz);
00040
00041 void Subdivide(int depth=1)const;
00042
00043 void SetOpenCondition(int* l_ec, int* r_ec);
00044 void SetOpenCondition(int ec);
00045
00046 private:
00047 void set_default_end_condition() { for(int i=0; i<dims; i++) left_ec[i] = right_ec[i] = open_end; }
00048 void convert2floatingends();
00049 void extrapolate2floating(int dir, bool left);
00050 void init_subdivision_data() { init_sbd_mesh(); convert2floatingends(); }
00051
00052 public:
00053 void bzr2floatingEndBspline(int dir);
00054 };
00055
00056
00057
00058 template<int dims, int sp_dims>
00059 inline SubdivisionManifold<dims, sp_dims> :: SubdivisionManifold(int arg1, ...)
00060 {
00061 int args[2*dims];
00062 get_reverse_ints_va(args, 2*dims);
00063 for(int i=dims-1; i>=0; i--)
00064 {
00065 deg[i] = args[2*i+1];
00066 len[i] = args[2*i];
00067 }
00068 ctl_msh.Resize(len);
00069 set_default_end_condition();
00070 }
00071 template<int dims, int sp_dims>
00072 inline SubdivisionManifold<dims, sp_dims> :: SubdivisionManifold(int* degsz)
00073 {
00074 for(int i=0; i<dims; i++)
00075 {
00076 deg[i] = degsz[2*i];
00077 len[i] = degsz[2*i+1];
00078 }
00079 msh.Resize(len);
00080 set_default_end_condition();
00081 }
00082
00083
00084 template<int dims, int sp_dims>
00085 void SubdivisionManifold<dims, sp_dims> :: SetOpenCondition(int* l_ec, int* r_ec)
00086 {
00087 memcpy(left_ec, l_ec, sizeof(int) * dims);
00088 memcpy(right_ec, r_ec, sizeof(int) * dims);
00089 }
00090 template<int dims, int sp_dims>
00091 void SubdivisionManifold<dims, sp_dims> :: SetOpenCondition(int ec)
00092 {
00093 fill(left_ec, left_ec+dims, ec);
00094 fill(right_ec, right_ec+dims, ec);
00095 }
00096 template<int dims, int sp_dims>
00097 void SubdivisionManifold<dims, sp_dims> :: convert2floatingends()
00098 {
00099 for(int i=0; i<dims; i++)
00100 {
00101 if(left_ec[i] == open_end && right_ec[i] == open_end && msh.GetSize(i) == deg[i] + 1)
00102 {
00103 cerr << "Subdivide() can only apply to tensor mesh of same degree in all directions.\n";
00104 bzr2floatingEndBspline(i);
00105 }
00106
00107 else
00108 {
00109 if(left_ec[i] == open_end)
00110 extrapolate2floating(i, true);
00111 if(right_ec[i] == open_end)
00112 extrapolate2floating(i, false);
00113 }
00114 }
00115 }
00116
00117
00118 template<typename T>
00119 struct affine_combine_inc_t1 : public binary_function<T, T const&, T const&>
00120 {
00121 affine_combine_inc_t1(double t_1, double t_2) : t1(t_1), t2(t_2) { }
00122 T operator()(T const& p1, T const& p2) { double t11 = t1++; return (p1 * t11 + p2 * t2) / (t11 + t2); }
00123 double t1, t2;
00124 };
00125 template<int dims, int sp_dims>
00126 void SubdivisionManifold<dims, sp_dims> :: extrapolate2floating(int dir, bool left)
00127 {
00128
00129 int d = deg[dir];
00130 for(row_iterator rw_itr = msh.RowIterate(dir); !rw_itr.PastEnd(); ++rw_itr)
00131 {
00132 int t10 = 2, t2 = -1;
00133 for(int i=1; i < d; i++, t10++, t2--)
00134 {
00135 int t1 = t10;
00136 if(left)
00137 transform(rw_itr.Begin(), rw_itr.Begin()+(d-i), rw_itr.Begin()+1, rw_itr.Begin(), affine_combine_inc_t1<point_t>(t1, t2));
00138 else
00139 transform(rw_itr.Rbegin(), rw_itr.Rbegin()+(d-i), rw_itr.Rbegin()+1, rw_itr.Rbegin(), affine_combine_inc_t1<point_t>(t1, t2));
00140 }
00141 }
00142 }
00143
00144 template<int dims, int sp_dims>
00145 void SubdivisionManifold<dims, sp_dims> :: bzr2floatingEndBspline(int dir)
00146 {
00147 cout << "\nctl mesh is\n" << msh << endl;
00148 int n = deg[dir];
00149 point_t deg2_mid_pnt;
00150 for(row_iterator rw_itr = msh.RowIterate(dir); !rw_itr.PastEnd(); ++rw_itr)
00151 {
00152 if(n==2)
00153 deg2_mid_pnt = *(rw_itr.Begin() + 1);
00154
00155 double *kv = new double[2 * n];
00156 fill(kv, kv+n, 0); fill(kv+n,kv+2*n, 1);
00157 TensorArray<point_t, 1> new_pnts(n+1);
00158 {
00159 Blossom<sp_dims> blsm(n, n);
00160 copy(rw_itr.Begin(), rw_itr.End()-1, blsm().Begin());
00161 blsm.KnotVector() = kv;
00162 for(int i = 0; i < n-1; i++)
00163 {
00164 blsm.Evaluate( -(i+1) );
00165 if( i > n-4 )
00166 new_pnts[n-2-i] = blsm()[n-2-i];
00167 else
00168 {
00169 Blossom<sp_dims> blsm2(blsm);
00170 blsm2.PopFont();
00171 for(int j=0; j<n-i-3; j++)
00172 blsm2.Evaluate(2+j);
00173 new_pnts[n-i-2] = blsm2()[0];
00174 }
00175 }
00176 }
00177 {
00178 Blossom<sp_dims> blsm(n, n);
00179 copy(rw_itr.Begin()+1, rw_itr.End(), blsm().Begin());
00180 blsm.KnotVector() = kv+1;
00181 for(int i = 0; i < n-1; i++)
00182 {
00183 blsm.Evaluate(2 + i);
00184 if( i > n-4 )
00185 new_pnts[2+i] = blsm()[0];
00186 }
00187 }
00188 copy(new_pnts.Begin(), new_pnts.End(), rw_itr.Begin());
00189 if(n==2)
00190 *(rw_itr.Begin() + 1) = deg2_mid_pnt;
00191
00192 cout << "\nctl mesh is\n" << msh << endl;
00193 }
00194 }
00195
00196 template<int dims, int sp_dims>
00197 void SubdivisionManifold<dims, sp_dims> :: Subdivide(int depth) const
00198 {
00199 int d = deg[0];
00200 for(int i=1; i<dims; i++)
00201 if( d != deg[i] )
00202 {
00203 cerr << "Subdivide() can only apply to tensor mesh of same degree in all directions.\n", exit(0);
00204 }
00205
00206 init_sbd_msh();
00207
00208 if(sbdl_msh.Empty())
00209 {
00210 original_msh = msh;
00211 convert2floatingends();
00212 }
00213
00214 msh.SetN(depth);
00215 while(depth--)
00216 {
00217 msh.InsertMiddlePoints();
00218 for(int i=2; i <= deg[0]; i++)
00219 msh.Averaging();
00220 }
00221 }
00222
00223
00224
00225
00226
00227 }
00228
00229 #endif