Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members   Examples  

SubdivisionManifold.H

Go to the documentation of this file.
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];             // floating, open, or periodic end conditions.
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++)               // evaluate n-1 times with u = -1, -2, ..., -(n-1).
00163         {
00164           blsm.Evaluate( -(i+1) );
00165           if( i > n-4 )                            // last two evaluations of i=n-3, i=n-2. Total evaluation times are n-2, and n-1.
00166             new_pnts[n-2-i] = blsm()[n-2-i];
00167           else                                     // have evaluated(to left) at u=-1,.. with i+1<= n-3 times so far, 
00168           {
00169             Blossom<sp_dims> blsm2(blsm);
00170             blsm2.PopFont();
00171             for(int j=0; j<n-i-3; j++)             // need to evaluate(to right) n-i-3 times, with u=2, 3,..
00172               blsm2.Evaluate(2+j);
00173             new_pnts[n-i-2] = blsm2()[0];          // blossom value at knot values starting at -(i+1), which is -(i+1)-(1-n)'th pnt.
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++)               // evaluate n-1 times with u = 2, 3, ..., n.
00182         {
00183           blsm.Evaluate(2 + i);
00184           if( i > n-4 )                            // last two evaluations of i=n-3, i=n-2.
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 }//end namespace xchen
00228 
00229 #endif

Generated on Wed Apr 7 21:40:49 2004 by doxygen1.2.18