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

TensorBlossom.H

Go to the documentation of this file.
00001 
00053 #ifndef _TENSORBLOSSOM_H
00054 #define _TENSORBLOSSOM_H
00055 
00056 #include <xstl.H>
00057 #include <TensorManifold.H>
00058 #include <Vector.H>
00059 #include <Combinatory.H>
00060 
00061 namespace xchen
00062 {
00063   
00064   enum { ruled, revolution, sweep };                              
00065 
00066   template <int dims, int sp_dims>
00067   struct generate_iso_functor;
00068   template <int dims, int sp_dims>
00069   struct draw_iso_functor;
00070 
00072   template<int dims=2, int sp_dims=3>
00073   class TensorBlossom : public TensorManifold<dims, sp_dims>
00074   {
00075       template<int dims2, int sp_dims2> friend class TensorBlossom;
00076       friend class glModel;
00077       template <int dims2, int sp_dims2> friend struct generate_iso_functor;
00078       template <int dims2, int sp_dims2> friend struct draw_iso_functor;
00079 
00080       def_type_name_for_tensor_manifold(dims, sp_dims);
00081       typedef TensorBlossom<dims, sp_dims> MyType;
00082       typedef TensorManifold<dims, sp_dims> BaseType;
00083       typedef TensorBlossom<dims-1,sp_dims> IsoMFType;
00084 
00085 #define SubMFType TensorBlossom<dims-1,from_sp_dims>
00086 
00087   private:
00088       knot_t ctl_kv;                                              // defining data: ctl_kv is the defining knot vectors.
00089       bool periodic[dims];                                        // defining data: periodic end condtions.
00090 
00091       vector<double> dmn[dims];                                   // derived data: break knots extracted from ctl_kv.
00092       bool domain_computed;                                       // For now assume unmutated after computed.
00093       
00094       knot_t sbd_kv;                                              // subdivision data: sbd_kv is for knot insertion and subdvion algo.
00095       vector< IsoMFType > iso_mf[dims];                           // iso sub_manifold at break points in each direction.
00096       
00097   public:
00098       template<int from_sp_dims>
00099       TensorBlossom(int mtd,SubMFType const*,SubMFType const* =0);
00100 
00101       TensorBlossom(int arg1, ...);                               
00102       TensorBlossom(mesh_t const& mesh);                          
00103       TensorBlossom& Transform(xchen::Transform const& trans);    
00104       
00105       knot_t& KnotVector() { return ctl_kv; }                            
00106       bool Insert(double u,int i=0);                                     
00107       bool IsPeriodicEnd(int i=0)           { return periodic[i]; }      
00108       void SetPeriodicEnd(int i=0,bool v=1) {periodic[i]=v; setKt(); }   
00109       void SetUniformFloatingEndKnots();                                 
00110       void SetUniformOpenEndKnots();                                     
00111 
00112       IsoMFType GetSubTensorBlossom(double u, int=0);                    
00113 
00114       void RaiseDegree(int inc=1, int i=0);                              
00115       void DecVarity(double*u){ForEachIofDims DecVarity(u[i],i);}        
00116       void DecVarity(double u, int i=0);                                 
00117 
00118       void Convert2FloatingEnd(int i)  { periodic2floating(i, ctldata);} 
00119       void Convert2Bzr(int i)          { convert2Bzr(i, ctldata); }      
00120       void Convert2OpenEnd(int i)      { convert2OpenEnd(i, ctldata); }  
00121       void Convert2Bzr()               { convert2Bzr(ctldata); }         
00122       void Convert2OpenEnd()           { convert2OpenEnd(ctldata); }     
00123       void Convert2FloatingEnd()       { periodic2floating(ctldata); }   
00124 
00125       void Subdivide(int depth=1)const;                                  
00126 
00127       friend ostream& operator<< <>(ostream& os, TensorBlossom const& rhs);
00128 
00129   private:
00130       template<int from_sp_dims> void construct_revolution_manifold(SubMFType const& rev_from);
00131       template<int from_sp_dims> void construct_ruled_manifold(SubMFType const& mf1, SubMFType const& mf2);
00132 
00133       enum { sbddata, ctldata };
00134       mesh_t& cur_msh(int applyon)                          { return applyon==sbddata? sbd_msh : ctl_msh; }
00135       knot_t& cur_kv(int applyon)                           { return applyon==sbddata? sbd_kv : ctl_kv; }
00136 
00137       bool insert(double u, int i, int applyon);      
00138       void blend(IdxRange const&, double u, int applyon);    // affine interpolation with u value at the given range.
00139       bool is_valid_range(IdxRange const& range, int on);
00140       
00141       void setKt() { ctl_kv.Clear(); ForEachIofDims ctl_kv[i].resize(periodic[i]? ctl_msh.GetSize(i)+1 : ctl_msh.GetSize(i) + deg[i] - 1); set_dflt_kt(); }
00142       void set_default_degs()                               { ForEachIofDims deg[i] = ctl_msh.GetSize(i)-1; }
00143 
00144       void init_sbd();                                      // init sbd data, and convert them to composite bzr.
00145       void init_sbd_knotvector(int i);                      // copy from ctl_kv and change to floating if periodic.
00146       void compact_sbd_kv();                                // sbd_kv is bzr form, delete the extra values.
00147       void subdivide_kv();                                  // insert middle value.
00148       void computeSegmentDomains();                         // Compute all break points for each direction based on ctl_kotvector, degree.
00149       void clean_sbd()                                      { BaseType::clean_sbd(); sbd_kv.Clear(); }
00150 
00151       void compute_1st_order_derivative();                  // all 1st order partial derivatives.
00152       void identifyEndPntsForPeriodicEnd(int i,int applyon);// periodic is implemented as open end. so this is to make sure no artificial gap.
00153 
00154       void periodic2floating(int i, int applyon);
00155       void periodic2floating(int applyon)                   { ForEachIofDims periodic2floating(i, applyon);  }       
00156       void convert2Bzr(int i, int applyon);                 // changes only made to subdivision data.
00157       void convert2Bzr(int applyon)                         { ForEachIofDims convert2Bzr(i, applyon);  }       
00158       void convert2OpenEnd(int i, int applyon);             // changes only made to subdivision data.
00159       void convert2OpenEnd(int applyon)                     { ForEachIofDims convert2OpenEnd(i, applyon);  }       
00160 
00161       void popFront(int i, int on)                          { cur_msh(on).PopFront(i); cur_kv(on)[i].erase(cur_kv(on)[i].begin());}//Erase front pnt&knot at i.
00162       void popBack(int i, int on)                           { cur_msh(on).PopBack(i); cur_kv(on)[i].pop_back(); }                  //Erase back pnt&knot at i.
00163 
00164       void unset_periodic()                                 { bzero(periodic, sizeof(bool) * dims); }
00165       void set_dflt_kt()                                    { SetUniformFloatingEndKnots(); }
00166 
00167       TensorBlossom(int deg[dims], int sz[dims]); 
00168       void GenerateUI()                               { BaseType::GenerateUI(); ui->AddboolControl("Draw Iso SubManifolds", 'i'); }   
00169       void Draw() const                               { BaseType::Draw();if(ui->GetboolControl("Draw Iso SubManifolds"))((MyType*)this)->draw_iso(); }
00170 
00171       void draw_iso();
00172       void generate_iso();
00173       void init_iso_generator()                             { iso_generator.blsm = this; }
00174       generate_iso_functor<dims, sp_dims> iso_generator;
00175   };
00176 
00177 
00178   template<int sp_dims> class TensorBlossom<0,sp_dims> { };
00179 
00180   
00181   template<int dims, int sp_dims>
00182   struct generate_iso_functor
00183   {
00184       bool first;    
00185       TensorBlossom<dims, sp_dims>* blsm;
00186       generate_iso_functor(TensorBlossom<dims, sp_dims>* _blsm=0) : first(true), blsm(_blsm) { }
00187       void operator()()
00188       {
00189         blsm->init_sbd();
00190         for(int i=0; i<dims; i++)
00191         {
00192           int sz[dims], dg[dims];
00193           blsm->sbd_msh.GetSize(sz);
00194           copy(sz+i+1, sz+dims, sz+i);
00195           copy(&blsm->deg[0], &blsm->deg[0]+i, dg);
00196           copy(&blsm->deg[0]+i+1, &blsm->deg[0]+dims, dg);
00197 
00198           // draw an iso every 2 * deg bzr segment. skip those already drawn by the previous calls.
00199           typename TensorBlossom<dims, sp_dims>::slc_iterator itr = blsm->sbd_msh.SliceIterate(i) + 2 * blsm->deg[i] * (first? 0 : 1); 
00200           int stride = (first? 2 : 4) * blsm->deg[i];
00201           for(; !itr.PastEnd(); itr += stride )
00202           {
00203             blsm->iso_mf[i].push_back( TensorBlossom<dims-1, sp_dims>(dg, sz) );
00204             copy(itr.Begin(), itr.End(), blsm->iso_mf[i].back().ControlMesh().Begin());    // copy the slice as the control mesh of the iso.
00205             blsm->iso_mf[i].back().rational = blsm->rational;
00206             
00207             int k = 0;
00208             for(int j=0; j<dims; j++)
00209             {
00210               if(j==i) continue;
00211               vector<double>::iterator out_itr = blsm->iso_mf[i].back().KnotVector()[k++].begin()-1;
00212               for(vector<double>::iterator itr = blsm->sbd_kv[j].begin(); itr != blsm->sbd_kv[j].end(); ++itr)
00213               {
00214                 for(int i=0; i<blsm->deg[i]; i++)
00215                   *(++out_itr) = *itr;        // expand the bzr compact form of sbd_kv.
00216               }
00217             }
00218           }
00219           for(typename vector< TensorBlossom<dims-1, sp_dims> >::iterator itr = blsm->iso_mf[i].begin(); itr != blsm->iso_mf[i].end(); ++itr)
00220           {
00221             itr->Subdivide();
00222           }
00223         }
00224         first = false;
00225       }
00226   };
00227   
00228   template<int dims, int sp_dims>
00229   struct draw_iso_functor
00230   {
00231       TensorBlossom<dims, sp_dims>& blsm;
00232       draw_iso_functor(TensorBlossom<dims, sp_dims>& _blsm) : blsm(_blsm) { }
00233       void operator()()
00234       {
00235         glPushAttrib(GL_LIGHTING_BIT);
00236         glDisable(GL_LIGHTING);
00237         wglShading(RGBAS(1.0,1.0,1.0,1.0,1.0));
00238         for(int i=0; i<dims; i++)
00239         {
00240           for(typename vector< TensorBlossom<dims-1, sp_dims> > :: iterator itr = blsm.iso_mf[i].begin(); itr != blsm.iso_mf[i].end(); ++itr)
00241           {
00242             itr->draw(itr->sbd_msh);
00243           }
00244         }
00245         glPopAttrib();
00246       }
00247   };
00248   
00249   
00250   template<int sp_dims>
00251   struct generate_iso_functor<1, sp_dims>
00252   {
00253       TensorBlossom<1, sp_dims>* blsm;
00254       generate_iso_functor(TensorBlossom<1, sp_dims>* =0) { }
00255       void operator()() { }
00256   };
00257   template<int sp_dims>
00258   struct draw_iso_functor<1, sp_dims>
00259   {
00260       draw_iso_functor(TensorBlossom<1, sp_dims>&) { }
00261       void operator()() { }
00262   };
00263   
00264   
00265 
00266   
00267   template<int dims, int sp_dims>
00268   inline TensorBlossom<dims, sp_dims> :: TensorBlossom(mesh_t const& m) : BaseType(m), domain_computed(false)
00269   {
00270     set_default_degs();
00271     unset_periodic();
00272     setKt();
00273     SetUniformOpenEndKnots();
00274     set2bzr_srf_type();
00275     init_iso_generator();
00276   }
00277   template<int dims, int sp_dims>
00278   inline TensorBlossom<dims, sp_dims> :: TensorBlossom(int arg1, ...) : domain_computed(false) 
00279   { 
00280     int args[2*dims];
00281     int sz[dims];
00282     get_reverse_ints_va(args, 2*dims); 
00283     for(int i=dims-1; i>=0; i--)
00284     {
00285       deg[i] = args[2*i+1];
00286       sz[i] = args[2*i];
00287     }
00288     ctl_msh.Resize(sz);
00289 
00290     unset_periodic();
00291     setKt();
00292     set2bsp_srf_type();
00293     init_iso_generator();
00294   }
00295 
00296 
00297   template<int dims, int sp_dims>
00298   inline TensorBlossom<dims, sp_dims> :: TensorBlossom(int dg[dims], int sz[dims]) : domain_computed(false) 
00299   { 
00300     copy(dg, dg+dims, deg);
00301     ctl_msh.Resize(sz);
00302 
00303     unset_periodic();
00304     setKt();
00305     set2bsp_srf_type();
00306     init_iso_generator();
00307   }
00308 
00309 
00310   template<int dims, int sp_dims>
00311   void TensorBlossom<dims, sp_dims> :: generate_iso() // compute isos in all end points of currrent sbudivided bzr
00312   {
00313     iso_generator();
00314   }
00315   
00316     
00317 
00318   template<int dims, int sp_dims>
00319   template<int from_sp_dims>
00320   inline TensorBlossom<dims, sp_dims> :: TensorBlossom(int method, SubMFType const*from_mf1, SubMFType const*from_mf2) : domain_computed(false)
00321   {
00322     switch(method)
00323     {
00324       case revolution: construct_revolution_manifold(*from_mf1); break;
00325       case ruled: construct_ruled_manifold(*from_mf1, *from_mf2); break;
00326     }
00327     init_iso_generator();
00328   }
00329   
00330   template<int dims, int sp_dims>
00331   void TensorBlossom<dims, sp_dims> :: 
00332   template<int from_sp_dims>
00333   construct_ruled_manifold(SubMFType const& from_mf1, SubMFType const & from_mf2)
00334   {
00335     SubMFType  mf1(from_mf1), mf2(from_mf2);
00336 
00337     cout << "mf1 is \n" << mf1 << endl;
00338     cout << "mf2 is \n" << mf2 << endl;
00339     
00340 
00341     mf1.Convert2OpenEnd(); mf2.Convert2OpenEnd();
00342     cout << "mf1 is \n" << mf1 << endl;
00343     cout << "mf2 is \n" << mf2 << endl;
00344     
00345     for(int i=0; i<dims-1; i++)
00346     {
00347       if(mf1.deg[i] > mf2.deg[i])
00348         mf2.RaiseDegree(mf1.deg[i] - mf2.deg[i], i);
00349       else if(mf1.deg[i] < mf2.deg[i])
00350         mf1.RaiseDegree(mf2.deg[i] - mf1.deg[i], i);
00351     }
00352     cout << "\n\nAfter degree raising\n";
00353     
00354     cout << "mf1 is \n" << mf1 << endl;
00355     cout << "mf2 is \n" << mf2 << endl;
00356     
00357     for(int i=0; i<dims-1; i++)
00358     {
00359       multiset<double> kv1(mf1.ctl_kv[i].begin(), mf1.ctl_kv[i].end()), kv2(mf2.ctl_kv[i].begin(), mf2.ctl_kv[i].end());
00360       multiset<double> kv12, kv21;    // kv12 = kv1 - kv2, ...
00361       set_difference( kv1.begin(), kv1.end(), kv2.begin(), kv2.end(), inserter(kv12, kv12.begin()) );
00362       set_difference( kv2.begin(), kv2.end(), kv1.begin(), kv1.end(), inserter(kv21, kv21.begin()) );
00363       for(multiset<double>::iterator itr = kv12.begin(); itr != kv12.end(); ++itr)
00364       {
00365         mf2.Insert(*itr, i);
00366       }
00367       cout << "\n\nAfter refine\n";
00368       cout << "mf2 is \n" << mf2 << endl;
00369       for(multiset<double>::iterator itr = kv21.begin(); itr != kv21.end(); ++itr)
00370       {
00371         mf1.Insert(*itr, i);
00372       }
00373       cout << "now mf1 is \n" << mf1 << endl;
00374       
00375       set_union( kv1.begin(), kv1.end(), kv2.begin(), kv2.end(), back_insert_iterator< vector<double> > (ctl_kv[i]) );
00376     }
00377     ctl_kv[dims-1].push_back(0); ctl_kv[dims-1].push_back(1);                    // knot vector for the ruled direction.
00378 
00379     int sz[dims]; mf1.ctl_msh.GetSize(sz); sz[dims-1] = 2; ctl_msh.Resize(sz);   // set ctl_msh size.
00380 
00381     slc_iterator itr = ctl_msh.SliceIterate(dims-1);                             // and then copy mf1 and mf2 as its two slices.
00382     copy(mf1.ctl_msh.Begin(), mf1.ctl_msh.End(), itr.Begin());
00383     copy(mf2.ctl_msh.Begin(), mf2.ctl_msh.End(), (++itr).Begin());
00384     
00385     copy(&mf1.deg[0], &mf1.deg[0] + dims - 1, deg); deg[dims-1] = 1;                     // Set deg in dims-1 to be linear and Copy the rest.
00386     copy(&mf1.periodic[0], &mf1.periodic[0] + dims - 1, periodic); periodic[dims-1] = 0; // UnSet periodic in dims-1 and Copy the rest.
00387     rational = from_mf1.rational || from_mf2.rational;                                   // rational if either of from_mf is.
00388 
00389     set2bsp_srf_type();
00390   }
00391   
00392     
00393   template<int dims, int sp_dims>
00394   void TensorBlossom<dims, sp_dims> :: 
00395   template<int from_sp_dims>
00396   construct_revolution_manifold(TensorBlossom<dims-1, from_sp_dims> const & _rev_from)
00397   {
00398     assert(sp_dims==4 && sp_dims>=from_sp_dims && dims>1);
00399 
00400     SubMFType & rev_from = (SubMFType&) _rev_from;
00401     
00402     int sz[dims]; rev_from.ControlMesh().GetSize(sz); sz[dims-1] = 8;        // sz[dims-1] is for ctrl point for the circle, the added manifold dimension.
00403     ctl_msh.Resize(sz);
00404     copy(rev_from.ctl_msh.Begin(), rev_from.ctl_msh.End(), ctl_msh.LinearIterate(dims-1, 0, 1));
00405     
00406     if(from_sp_dims == sp_dims)
00407     {
00408       assert(rev_from.IsRational());
00409     }
00410     else
00411     {
00412       assert(from_sp_dims + 1 == sp_dims || from_sp_dims + 2 == sp_dims);
00413       
00414       for(linear_iterator itr = ctl_msh.LinearIterate(dims-1, 0, 1); !itr.PastEnd(); ++itr)
00415       {
00416         if(from_sp_dims == 3 && rev_from.IsRational()) // 1D or 2D R in P2.
00417         {
00418           (*itr)[sp_dims-1] = (*itr)[2];               // [2] is originally weight component.
00419           (*itr)[2] = 0;  
00420         }
00421         else                                            // 1D or 2D P in E2 or E3 
00422           (*itr)[sp_dims-1] = 1.0;                      // add weight component.
00423       }
00424     }
00425     /* rotate each original ctl point around Y-axis to generate new contol points. */
00426     for(row_iterator r_itr = ctl_msh.RowIterate(dims-1); !r_itr.PastEnd(); ++r_itr)
00427     {
00428       element_iterator itr0 = r_itr.Begin();
00429       element_iterator itr = r_itr.Begin();
00430 
00431       point_t& p = *itr0;
00432       double w = sqrt(2.0) / 2;
00433       double ang = 45;
00434 
00435       (*++itr) = rY(ang)(p).Syw(w);
00436 
00437       for(++itr, ang += 45; itr != r_itr.End(); ++itr, ang += 45)
00438       {
00439         (*itr) = rY(ang)(p);
00440         ang += 45;
00441         (*++itr) = rY(ang)(p).Syw(w);
00442       }
00443     }
00444     for(int i=0; i<dims-1; i++)                                    // copy the original knot vectors.
00445     {
00446       copy(rev_from.ctl_kv[i].begin(), rev_from.ctl_kv[i].end(), back_insert_iterator< vector<double> >(ctl_kv[i]) );
00447     }
00448     for(int i=0; i<4; i++)                                         // set knot vector along the parallel to be 0,0,1,1,2,2,3,3,4.
00449     {
00450       ctl_kv[dims-1].push_back(i); ctl_kv[dims-1].push_back(i);
00451     }
00452     ctl_kv[dims-1].push_back(4);
00453 
00454     copy(rev_from.deg, rev_from.deg + dims-1, deg);                 // copy degrees.
00455     copy(rev_from.periodic, rev_from.periodic + dims-1, periodic);  // copy periodic condition.
00456 
00457     deg[dims-1] = 2;                                                // Set deg in dims-1 to be quadratic and,
00458     periodic[dims-1] = true;                                        // of course periodic and
00459     IsRational() = true;                                            // rational.
00460 
00461     set2bsp_srf_type();
00462   }
00463   
00464       
00465     
00466   template<int dims, int sp_dims>
00467   inline TensorBlossom<dims, sp_dims>& TensorBlossom<dims, sp_dims>::Transform(xchen::Transform const& trans)
00468   {
00469     ctl_msh.Transform(trans);
00470     clean_sbd();
00471     return *this;
00472   }
00473   
00474     
00475   template<int dims, int sp_dims>
00476   inline void TensorBlossom<dims, sp_dims> :: SetUniformFloatingEndKnots()
00477   {
00478     for(int i=0; i<dims; i++)
00479     {
00480       generate( ctl_kv[i].begin(), ctl_kv[i].end(), iota<double>(0.0) );
00481     }
00482   }
00483   template<int dims, int sp_dims>
00484   inline void TensorBlossom<dims, sp_dims> :: SetUniformOpenEndKnots()
00485   {
00486     for(int i=0; i<dims; i++)
00487     {
00488       vector<double>::iterator itr = ctl_kv[i].begin() + deg[i];
00489 
00490       fill(ctl_kv[i].begin(), itr, 0.0);
00491 
00492       double u = 1.0;
00493       for(; itr != ctl_kv[i].end() - deg[i]; ++itr, ++u)
00494         *itr = u;
00495       
00496       fill(itr, ctl_kv[i].end(), u);
00497     }
00498   }
00499 
00500   template<int dims, int sp_dims>
00501   void TensorBlossom<dims, sp_dims> :: init_sbd()
00502   {
00503     if(sbd_initialized) return;
00504     
00505     BaseType::init_sbd(); 
00506     if(!domain_computed) computeSegmentDomains(); 
00507 
00508     for(int i=0; i<dims; i++)
00509     {
00510       init_sbd_knotvector(i);
00511       convert2Bzr(i, sbddata);
00512     }
00513     compact_sbd_kv();
00514     sbd_initialized = true;
00515   }
00516 
00517 
00518   template<int dims, int sp_dims>
00519   void TensorBlossom<dims, sp_dims> :: compact_sbd_kv()
00520   {
00521     for(int i=0; i<dims; i++)
00522     {
00523       vector<double>::iterator in_itr = sbd_kv[i].begin() + deg[i]-1, out_itr = sbd_kv[i].begin();
00524       for(; in_itr != sbd_kv[i].end()+deg[i]-1; in_itr += deg[i], ++out_itr)
00525       {
00526         *out_itr = *in_itr;
00527       }
00528       sbd_kv[i].erase(out_itr, sbd_kv[i].end());
00529     }
00530   }
00531   
00532   template<int dims, int sp_dims>
00533   void TensorBlossom<dims, sp_dims> :: subdivide_kv()
00534   {
00535     for(int i=0; i<dims; i++)
00536     {
00537       vector<double>& kv = (vector<double>&) sbd_kv[i];
00538       vector<double> old_kt(kv);
00539       kv.resize(2*old_kt.size()-1);
00540       vector<double>::iterator itr1 = old_kt.begin(), itr2 = itr1 + 1, itr = kv.begin()-1;
00541       for(; itr2 != old_kt.end(); ++itr1, ++itr2)
00542       {
00543         *(++itr) = *itr1; *(++itr) = (*itr1 + *itr2)/2;
00544       }
00545       *(++itr) = *itr1; 
00546     }
00547   }
00548   
00549 
00550   template<int dims, int sp_dims>
00551   void TensorBlossom<dims, sp_dims> :: init_sbd_knotvector(int i)
00552   {
00553     sbd_kv[i] = ctl_kv[i];
00554     if(periodic[i]) 
00555       periodic2floating(i, sbddata);
00556   }
00557 
00558   template<int dims, int sp_dims>
00559   void TensorBlossom<dims, sp_dims> :: periodic2floating(int i, int applyon)
00560   {
00561     knot_t& kv = cur_kv(applyon);
00562     mesh_t& msh = cur_msh(applyon); 
00563 
00564     double T = kv[i].back() - kv[i].front();        // modula of T
00565     vector<double> newkv;
00566     back_insert_iterator< vector<double> > bitr(newkv);
00567         
00568     transform(kv[i].end()-deg[i], kv[i].end()-1, bitr, bind2nd(minus<double>(), T));     // copy the last deg-1 upto back() ele(-T).
00569     copy(kv[i].begin(), kv[i].end(), bitr);                                              // copy the whole knots
00570     transform(kv[i].begin()+1, kv[i].begin()+deg[i], bitr, bind2nd(plus<double>(), T));  // copy the first deg-1 ele(+T).
00571 
00572     kv[i] = newkv;
00573 
00574     int extendRL[2*dims];                                                // will append front deg-1 and back 1 extra pnts.
00575     bzero(extendRL, sizeof(int) * 2 * dims);
00576     extendRL[2*i] = 1; extendRL[2*i+1] = deg[i] - 1;
00577     msh.Extend(extendRL);
00578     
00579     array_copy(i, deg[i]-1,  msh, msh.GetSize(i) - deg[i],  msh, 0);     // fill the left expanded deg-1 elements from the right eles(before expanded).
00580     array_copy(i, 1,  msh, deg[i]-1,  msh, msh.GetSize(i) - 1);          // fill the right expanded 1 element from the first(before expanded) 
00581 
00582     if(applyon==ctldata)
00583       periodic[i] = 0;
00584   }
00585     
00586 
00587   template<int dims, int sp_dims>
00588   inline void TensorBlossom<dims, sp_dims> :: identifyEndPntsForPeriodicEnd(int i, int applyon)
00589   {
00590     if(periodic[i])
00591     {
00592       mesh_t msh = cur_msh(applyon);
00593       if(msh.GetSize(i) > 1)
00594         for(row_iterator itr = msh.RowIterate(i); !itr.PastEnd(); ++itr)
00595           *(itr.End()-1) = *(itr.Begin());
00596     }
00597   }
00598   
00599   
00600   template<int dims, int sp_dims>
00601   inline void TensorBlossom<dims, sp_dims> :: convert2Bzr(int i, int applyon)
00602   {
00603     convert2OpenEnd(i, applyon);
00604 
00605     if(dmn[i].size() > 2)
00606     {
00607       vector<double>::iterator itr = dmn[i].begin()+1, end_itr = dmn[i].end() - 1;
00608       for(; itr != end_itr; ++itr)
00609       {
00610         while(insert(*itr, i, applyon));
00611       }
00612     }
00613   }
00614 
00615   template<int dims, int sp_dims>
00616   inline void TensorBlossom<dims, sp_dims> :: convert2OpenEnd(int i, int applyon)
00617   {
00618     knot_t& kv = cur_kv(applyon);
00619     mesh_t& msh = cur_msh(applyon); 
00620 
00621     if(!domain_computed) computeSegmentDomains(); 
00622     
00623     if(applyon==ctldata && periodic[i])
00624     {
00625       periodic2floating(i, ctldata);
00626     }
00627     while( insert(dmn[i].front(), i, applyon) ) { popFront(i, applyon);  }
00628     while( kv[i].front() != dmn[i].front() )     popFront(i, applyon);
00629 
00630     while( insert(dmn[i].back(), i, applyon) )  { popBack(i, applyon);}
00631     while( kv[i].back() != dmn[i].back() )       popBack(i, applyon);
00632 
00633     identifyEndPntsForPeriodicEnd(i, applyon);
00634   }
00635   
00636   
00637   template<int dims, int sp_dims>
00638   void TensorBlossom<dims, sp_dims> :: computeSegmentDomains() 
00639   { 
00640     for(int i=0; i<dims; i++)
00641     {
00642       if(!dmn[i].size())
00643       {
00644         vector<double>::iterator itr1 = periodic[i]? ctl_kv[i].begin() : ctl_kv[i].begin() + deg[i] - 1;
00645         dmn[i].push_back(*itr1);
00646       
00647         vector<double>::iterator itr2 = itr1 + 1;
00648         for(; itr2 != (periodic[i]? ctl_kv[i].end() : ctl_kv[i].end() - deg[i] + 1); ++itr1, ++itr2)
00649         {
00650           if(*itr1 != *itr2)
00651           {
00652             dmn[i].push_back(*itr2);
00653           }
00654         }
00655       }
00656     }
00657     domain_computed = true;
00658   }
00659   
00660   template<int dims, int sp_dims>
00661   void TensorBlossom<dims, sp_dims> :: RaiseDegree(int inc, int dir) 
00662   {
00663     Convert2Bzr(dir);
00664 
00665     mesh_t old_msh(ctl_msh);
00666     ctl_msh.ExtendAtDirection(dir, 0, inc * (ctl_msh.GetSize(dir) - 1) / deg[dir]);
00667     fill(ctl_msh.Begin(), ctl_msh.End(), point_t(0.0));
00668 
00669     int n = deg[dir],  new_deg = n+inc;
00670     
00671     linear_iterator* out_itr = new linear_iterator[new_deg];                // iterate each pnt in a bzr polygon for the new mesh.
00672 
00673     slc_iterator itr = old_msh.SliceIterate(dir); 
00674     for(int poly = 0; poly < (old_msh.GetSize(dir) - 1) / n; poly++)        // iterate all bzr control 1D polygon along i direction.
00675     {
00676       for(int i=0; i < new_deg; i++)
00677         out_itr[i] = ctl_msh.LinearIterate(dir, poly * new_deg + i, 1);     // used to iterate all slices other than the right end one.
00678       
00679       for(int i=0; i <= n; ++i, ++itr)                                      // iterate all pnts within the polygon.
00680       {
00681         for(int j=0; j <= inc; j++)                                         // b<0^(n-i)1^i> contributing to b<0^(n-i + inc-j)1^(i + j)>
00682         {
00683           if( (!i && !j) || (i==n && j==inc) ) continue;                    // can only contribute to the two end pnts.
00684           
00685           transform(itr.Begin(), itr.End(), out_itr[i+j].Begin(), out_itr[i+j].Begin(), 
00686                     Scale1stAdd<point_t>( C(j, i+j) * C(inc-j,  n-i + inc-j) ));
00687         }
00688       }
00689       --itr;                                                                // the last pnt of this poly is also the first pnt of the next poly.
00690     }
00691     delete [] out_itr;
00692     
00693     transform( ctl_msh.Begin(), ctl_msh.End(), ctl_msh.Begin(), ScaleAll<point_t>( 1.0/C(inc, n + inc) ) );   // make it affine combination.
00694     slc_iterator itr1 = old_msh.SliceIterate(dir), itr2 = ctl_msh.SliceIterate(dir);                  // and copy all the end points of bzr polys.
00695     for(; !itr1.PastEnd(); itr1 += n, itr2 += new_deg)
00696     {
00697       copy(itr1.Begin(), itr1.End(), itr2.Begin());
00698     }
00699 
00700     deg[dir] += inc;
00701     for(vector<double>::iterator itr = dmn[dir].begin(); itr != dmn[dir].end(); ++itr)
00702       for(int i=0; i<inc; i++)
00703         ctl_kv.Insert(*itr, dir);
00704     
00705     clean_sbd();
00706     return;
00707   }
00708 
00709   template<int dims, int sp_dims>
00710   inline bool TensorBlossom<dims, sp_dims> :: is_valid_range(IdxRange const& range, int applyon)
00711   {
00712     return range.s+1 < range.e && range.s >=0 && range.e <= cur_msh(applyon).GetSize(range.d);
00713   }
00714   
00715   template<int dims, int sp_dims>
00716   inline bool TensorBlossom<dims, sp_dims> :: Insert(double u,int i)
00717   { 
00718     return !periodic[i] && insert(u,i,ctldata); 
00719   }
00720   template<int dims, int sp_dims>
00721   bool TensorBlossom<dims, sp_dims> :: insert(double u, int dir, int applyon)
00722   {
00723     assert(deg[dir]);    
00724 
00725     knot_t& kv = cur_kv(applyon);
00726     mesh_t& msh = cur_msh(applyon);
00727     
00728     TensorBlossom<dims, sp_dims>*This = (TensorBlossom<dims, sp_dims>*)this;
00729     
00730     int repeat;                                          // The multiplicity of the u value in current knot vector.
00731     int idx = kv.UpperBound(u, repeat, dir) - deg[dir];  // First idx such that kv[dir][idx] > u - deg = 1st pnt of the seg where u is defined.
00732     IdxRange range(dir, idx, idx + deg[dir] + 1 - repeat);
00733 
00734     if( ! is_valid_range(range, applyon) ) return false;
00735 
00736     vector<point_t> first_pnts;      // save these first pnts as they are going to be overwritten by insert().
00737     copy( msh.LinearIterate(dir,idx,1).Begin(), msh.LinearIterate(dir,idx,1).End(), back_insert_iterator<vector<point_t> >(first_pnts) );
00738 
00739     This->blend(range, u, applyon);           // blending ctl points. the first pnt is overwritten, and the last pnt is kept.
00740     kv.Insert(u, dir);               // insert the u knot value.
00741 
00742     if(dims==1)               
00743       msh.Insert(msh.Begin() + idx, first_pnts.front());
00744     else 
00745     {
00746       msh.Insert(dir, idx);
00747       copy(first_pnts.begin(), first_pnts.end(), msh.LinearIterate(dir, idx, 1));   // now restore the first pnt.
00748     }
00749     return true;
00750   }
00751   
00752 
00753   template<int dims, int sp_dims>
00754   inline void TensorBlossom<dims, sp_dims> :: DecVarity(double u, int dir)
00755   {
00756     for(row_iterator itr = ctl_msh.RowIterate(dir); !itr.PastEnd(); ++itr)
00757     {
00758       insert(dir, itr.Begin(), itr.End(), itr.Begin(), 0, u);
00759     }
00760 
00761     deg[dir]--;
00762     ctl_msh.ResizeOneDirection(dir, ctl_msh.GetSize(dir)-1);
00763     ctl_kv[dir].pop_back();
00764     ctl_kv[dir].erase(ctl_kv[dir].begin());
00765   }
00766 
00767 
00768   template<int dims, int sp_dims>
00769   inline void TensorBlossom<dims, sp_dims> :: blend(IdxRange const& range, double u, int applyon) 
00770   {
00771     knot_t& kv = cur_kv(applyon);
00772     mesh_t& msh = cur_msh(applyon);
00773 
00774     int d = range.d, s = range.s, e = range.e;
00775     int i = s,  j = s + deg[d];
00776     slc_iterator 
00777       input1 = msh.SliceIterate(d, s, e-1), 
00778       input2 = msh.SliceIterate(d, s+1, e), 
00779       output = msh.SliceIterate(d, s, e-1); 
00780 
00781     for(; !input1.PastEnd(); ++input1, ++input2, ++output, ++i, ++j)
00782     {
00783       transform(input1.Begin(), input1.End(), input2.Begin(), output.Begin(), 
00784                 AffineCombine<point_t>( (u - kv[d][i]) / (kv[d][j] - kv[d][i]) ));
00785     }
00786   }
00787   
00788   template<int dims, int sp_dims>
00789   void TensorBlossom<dims, sp_dims> :: Subdivide(int depth) const
00790   {
00791     TensorBlossom<dims, sp_dims>*This = ((TensorBlossom<dims, sp_dims>*)this);
00792     This->init_sbd();
00793     mesh_t& msh = This->sbd_msh;
00794 
00795     msh.SetN(depth);
00796     while(depth--)
00797     {
00798       msh.InsertMiddlePoints(false);
00799       for(int i=0; i<dims; i++)
00800       {
00801         for(slc_iterator itr = msh.SliceIterate(i); !(itr+1).PastEnd(); itr += 2*deg[i])           // iterate all bzr control 1D polygon along i direction.
00802         {
00803           slc_iterator left_itr0(itr), middle_itr0(itr + 1), right_itr0(itr + 2); 
00804 
00805           for(int j=0; j < deg[i]; j++, ++left_itr0, ++right_itr0, ++middle_itr0)                  // de-castejau algo from level 0 to level deg[i]-1.
00806           {
00807             slc_iterator left_itr(left_itr0), right_itr(right_itr0), middle_itr(middle_itr0);
00808 
00809             for(int k=0; k<deg[i]-j;  k++, left_itr += 2, right_itr += 2, middle_itr += 2)         // de-castejau algo level j.
00810             {
00811               transform(left_itr.Begin(), left_itr.End(), right_itr.Begin(), middle_itr.Begin(), Average<point_t>() );
00812             }
00813           }
00814         }
00815       }
00816       This->subdivide_kv();
00817     }
00818     This->compute_1st_order_derivative();
00819     //    This->generate_iso();
00820   }
00821 
00822   template<int dims, int sp_dims>
00823   void TensorBlossom<dims, sp_dims> :: compute_1st_order_derivative()
00824   {
00825     if(dims>2) return;
00826     
00827     int sz[dims];
00828     sbd_msh.GetSize(sz);
00829     for(int i=0; i<dims; i++) sz[i] = (sz[i]-1) / deg[i] + 1; 
00830     for(int i=0; i<dims; i++) Dmsh[i].Resize(sz);
00831 
00832     for(int i=0; i<dims; i++)
00833     {
00834       row_iterator msh_row_itr = sbd_msh.RowIterate(i), Dmsh_row_itr = Dmsh[i].RowIterate(i);
00835 
00836       for(; !Dmsh_row_itr.PastEnd(); ++Dmsh_row_itr, msh_row_itr += deg[(i+1)%dims])   // only for dims == 2;  need more general algo here.
00837       {
00838         element_iterator msh_ele_itr1 = msh_row_itr.Begin(), msh_ele_itr2 = msh_row_itr.Begin() + 1, Dmsh_ele_itr = Dmsh_row_itr.Begin();
00839 
00840         for(; msh_ele_itr2 < msh_row_itr.End(); msh_ele_itr1 += deg[i], msh_ele_itr2 += deg[i], ++Dmsh_ele_itr)
00841         {
00842           *Dmsh_ele_itr = *msh_ele_itr2 - *msh_ele_itr1;       // need to be scaled by domain interval and deg.
00843         }
00844         *Dmsh_ele_itr = *msh_ele_itr1 - *(msh_ele_itr1-1);
00845         if(dims==1) break;
00846       }
00847     }
00848     if(IsRational())
00849     {
00850       for(int i=0; i<dims; i++)      // compute 1st order partial derivative along direction i.
00851       {
00852         linear_iterator Dmsh_itr = Dmsh[i].Begin();
00853         for(row_iterator msh_row_itr = sbd_msh.RowIterate(0); !msh_row_itr.PastEnd(); msh_row_itr += deg[1]) //assume dims==2 now.
00854         {
00855           int count = 0;
00856           for(element_iterator msh_itr = msh_row_itr.Begin(); msh_itr <  msh_row_itr.End(); msh_itr += deg[0], ++Dmsh_itr)
00857           {
00858             double w = (*msh_itr)[3], w1 = (*Dmsh_itr)[3];          // last components of the point and the derivative
00859             Vector<double, sp_dims-1> p(*msh_itr), p1(*Dmsh_itr);   // the point and the derivative without last component.
00860             *Dmsh_itr = (w * p1 - w1 * p) / (w * w);
00861           }
00862           if(dims==1) break;
00863         }
00864       }
00865     }
00866     if(dims==2)
00867     {
00868       Nmsh.Resize(sz);
00869       transform(Dmsh[1].Begin(), Dmsh[1].End(), Dmsh[0].Begin(), Nmsh.Begin(), cross_product());
00870     }
00871   }
00872   
00873   template<int dims, int sp_dims>
00874   inline void TensorBlossom<dims, sp_dims> :: draw_iso()
00875   {
00876     draw_iso_functor<dims, sp_dims>(*this)();
00877   }
00878   
00879         
00880   template<int dims, int sp_dims>
00881   ostream& operator<< (ostream& os, TensorBlossom<dims, sp_dims> const& _blsm)
00882   {
00883     TensorBlossom<dims, sp_dims>& blsm = (TensorBlossom<dims, sp_dims> &) _blsm;
00884     
00885     os << "The " << (blsm.IsRational()? "rational" : "polynomial") << " blossom has,\nControl Mesh = \n" << blsm.ctl_msh << endl;
00886     os << "Degrees = \t[";
00887     for(int i=dims-1; i; i--)
00888       os << blsm.deg[i] << " ";
00889     os << blsm.deg[0] << "]\n\n";
00890     os << "Knot vectors =\t";
00891     for(int i=dims-1; i>=0; i--) 
00892     {
00893       os << "[" << (blsm.IsPeriodicEnd(i)? "Periodic: " : ""); 
00894       copy(blsm.ctl_kv[i].begin(), blsm.ctl_kv[i].end()-1, ostream_iterator<double>(os, " ")); os << blsm.ctl_kv[i].back() << "]\t";
00895     }
00896     os << endl;
00897 
00898     return os;
00899   }
00900 
00901 
00902 
00903 
00904   template<int dims, int sp_dims>
00905   inline TensorBlossom<dims, sp_dims> operator*(Transform const& trans, TensorBlossom<dims, sp_dims>const& ar)
00906   {
00907     TensorBlossom<dims, sp_dims> ret(ar);
00908     ret.Transform(trans);
00909     return ret;
00910   }
00911   
00912     
00913 }//end namespace xchen
00914 
00915 
00916 #endif

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