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;
00089 bool periodic[dims];
00090
00091 vector<double> dmn[dims];
00092 bool domain_computed;
00093
00094 knot_t sbd_kv;
00095 vector< IsoMFType > iso_mf[dims];
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);
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();
00145 void init_sbd_knotvector(int i);
00146 void compact_sbd_kv();
00147 void subdivide_kv();
00148 void computeSegmentDomains();
00149 void clean_sbd() { BaseType::clean_sbd(); sbd_kv.Clear(); }
00150
00151 void compute_1st_order_derivative();
00152 void identifyEndPntsForPeriodicEnd(int i,int applyon);
00153
00154 void periodic2floating(int i, int applyon);
00155 void periodic2floating(int applyon) { ForEachIofDims periodic2floating(i, applyon); }
00156 void convert2Bzr(int i, int applyon);
00157 void convert2Bzr(int applyon) { ForEachIofDims convert2Bzr(i, applyon); }
00158 void convert2OpenEnd(int i, int applyon);
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());}
00162 void popBack(int i, int on) { cur_msh(on).PopBack(i); cur_kv(on)[i].pop_back(); }
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
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());
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;
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()
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;
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);
00378
00379 int sz[dims]; mf1.ctl_msh.GetSize(sz); sz[dims-1] = 2; ctl_msh.Resize(sz);
00380
00381 slc_iterator itr = ctl_msh.SliceIterate(dims-1);
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;
00386 copy(&mf1.periodic[0], &mf1.periodic[0] + dims - 1, periodic); periodic[dims-1] = 0;
00387 rational = from_mf1.rational || from_mf2.rational;
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;
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())
00417 {
00418 (*itr)[sp_dims-1] = (*itr)[2];
00419 (*itr)[2] = 0;
00420 }
00421 else
00422 (*itr)[sp_dims-1] = 1.0;
00423 }
00424 }
00425
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++)
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++)
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);
00455 copy(rev_from.periodic, rev_from.periodic + dims-1, periodic);
00456
00457 deg[dims-1] = 2;
00458 periodic[dims-1] = true;
00459 IsRational() = true;
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();
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));
00569 copy(kv[i].begin(), kv[i].end(), bitr);
00570 transform(kv[i].begin()+1, kv[i].begin()+deg[i], bitr, bind2nd(plus<double>(), T));
00571
00572 kv[i] = newkv;
00573
00574 int extendRL[2*dims];
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);
00580 array_copy(i, 1, msh, deg[i]-1, msh, msh.GetSize(i) - 1);
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];
00672
00673 slc_iterator itr = old_msh.SliceIterate(dir);
00674 for(int poly = 0; poly < (old_msh.GetSize(dir) - 1) / n; poly++)
00675 {
00676 for(int i=0; i < new_deg; i++)
00677 out_itr[i] = ctl_msh.LinearIterate(dir, poly * new_deg + i, 1);
00678
00679 for(int i=0; i <= n; ++i, ++itr)
00680 {
00681 for(int j=0; j <= inc; j++)
00682 {
00683 if( (!i && !j) || (i==n && j==inc) ) continue;
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;
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) ) );
00694 slc_iterator itr1 = old_msh.SliceIterate(dir), itr2 = ctl_msh.SliceIterate(dir);
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;
00731 int idx = kv.UpperBound(u, repeat, dir) - deg[dir];
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;
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);
00740 kv.Insert(u, dir);
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));
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])
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)
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)
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
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])
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;
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++)
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])
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];
00859 Vector<double, sp_dims-1> p(*msh_itr), p1(*Dmsh_itr);
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 }
00914
00915
00916 #endif