G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsTensorBSpline.hpp
Go to the documentation of this file.
1 
15 #pragma once
16 
18 
19 #include <gsNurbs/gsBSpline.h>
21 #include <gsNurbs/gsBoehm.h>
22 
23 #include <gsIO/gsXml.h>
25 
26 #include <gsTensor/gsTensorTools.h>
27 
28 namespace gismo
29 {
30 
31 template<short_t d, class T>
32 void constructCoefsForSlice(index_t dir_fixed, index_t index,
33  const gsMatrix<T> & fullCoefs,
34  const gsVector<index_t,d> & sizes,
35  gsMatrix<T>& result)
36 {
37  gsVector<index_t,d> lowerCorner, upperCorner;
38  lowerCorner.setZero();
39  upperCorner = sizes;
40  lowerCorner[dir_fixed] = index;
41  upperCorner[dir_fixed] = index + 1;
42  // to do: gsMatrix<index_t> ind = gsTensorBasis::coefSlice(dim_fixed, index) ?
43 
44  // Collect the boundary coefficients
45  result.resize( sizes.prod() / sizes[dir_fixed], fullCoefs.cols() );
46  gsVector<index_t,d> str, cur = lowerCorner;
47  tensorStrides(sizes,str);
48  index_t r = 0;
49  do {
50  result.row(r++) = fullCoefs.row( cur.dot(str) );
51  } while ( nextLexicographic(cur, lowerCorner, upperCorner) );
52 }
53 
54 template<short_t d, class T>
56  KnotVectorType KV1, KnotVectorType KV2)
57 {
58  GISMO_ASSERT(d==2, "Wrong dimension: tried to make a "<< d<<"D tensor B-spline using 2 knot-vectors.");
59 
60  std::vector<Family_t*> cbases;
61  const int n1 = KV1.size() - KV1.degree() - 1;
62  const int n2 = KV2.size() - KV2.degree() - 1;
63 
64  cbases.push_back(new gsBSplineBasis<T>(give(KV1)) );
65  cbases.push_back(new gsBSplineBasis<T>(give(KV2)) );
66  Basis * tbasis = Basis::New(cbases); //d==2
67 
68 
69  GISMO_ASSERT( (corner.rows()==4) && (corner.cols()==3),
70  "gsTensorBSpline: Please make sure that the size of *corner* is 4-by-3");
71 
72  gsMatrix<T> pcp (n1*n2, 3);
73  // set up CPs on boundary first. The inner CPs on each boundary curve are
74  // uniformly linear dependent on the two corner CPs
75  int j=0; // boundary v=0
76  for (int i=0; i<=n1-1; i++)
77  {
78  for (unsigned int xi=0; xi<=2; xi++) //specification of x or y or z
79  {
80  pcp(i+j*n1,xi)=corner(0,xi) + i/((T)(n1-1))*( corner(1,xi) - corner(0,xi) );
81  }
82  }
83  j=n2-1; // boundary v=1
84  for (int i=0; i<=n1-1; i++)
85  {
86  for (unsigned int xi=0; xi<=2; xi++) //specification of x or y or z
87  {
88  pcp(i+j*n1,xi)=corner(3,xi) + i/((T)(n1-1))*( corner(2,xi) - corner(3,xi) );
89  }
90  }
91  int i=0; // boundary u=0;
92  for (j=0; j<=n2-1; j++)
93  {
94  for (unsigned int xi=0; xi<=2; xi++) //specification of x or y or z
95  {
96  pcp(i+j*n1,xi)=corner(0,xi) + j/((T)(n2-1))*( corner(3,xi) - corner(0,xi) );
97  }
98  }
99  i=n1-1; // boundary u=1;
100  for (j=0; j<=n2-1; j++)
101  {
102  for (unsigned int xi=0; xi<=2; xi++) //specification of x or y or z
103  {
104  pcp(i+j*n1,xi)=corner(1,xi) + j/((T)(n2-1))*( corner(2,xi) - corner(1,xi) );
105  }
106  }
107  // uniformly linear dependent in horizontal direction
108  for (j=1; j<=n2-2; j++)
109  {
110  for (i=1; i<=n1-2; i++)
111  {
112  for (unsigned int xi=0; xi<=2; xi++) //specification of x or y or z
113  {
114  pcp(i+j*n1,xi)=pcp(0+j*n1,xi) + i/((T)(n1-1))*( pcp(n1-1+j*n1,xi)-pcp(0+j*n1,xi) );
115  }
116  }
117  }
118 
119  this->m_basis = tbasis;
120  this->m_coefs.swap( pcp );
121 }
122 
123 // todo: move to hpp
124 template<short_t d, class T>
126  BoundaryGeometryType & result) const
127 {
128  GISMO_ASSERT(d-1>=0,"d must be greater or equal than 1");
129  GISMO_ASSERT(dir_fixed>=0 && static_cast<unsigned>(dir_fixed)<d,"cannot fix a dir greater than dim or smaller than 0");
130  // construct the d-1 basis
131  boxSide side(dir_fixed,0);
132  typename BoundaryBasisType::uPtr tbasis = this->basis().boundaryBasis(side);
133 
134  if(d==1)
135  {
136  gsMatrix<T> val(1,1),point;
137  val(0,0)=par;
138  this->eval_into(val,point);
139  result = BoundaryGeometryType(*tbasis, point );
140  }
141  else
142  {
143  const int mult = this->basis().knots(dir_fixed).multiplicity(par);
144  const int degree = this->basis().degree(dir_fixed);
145  index_t index;
146  gsMatrix<T> coefs;
147  if( mult>=degree )
148  {
149  // no knot insertion needed, just extract the right coefficients
150  const gsKnotVector<T>& knots = this->basis().knots(dir_fixed);
151  if (par == *knots.domainEnd())
152  index = knots.size()-this->basis().degree(dir_fixed)-2;
153  else
154  index = (knots.iFind(par) - knots.begin()) - this->basis().degree(dir_fixed);
155  gsVector<index_t,d> sizes;
156  this->basis().size_cwise(sizes);
157  constructCoefsForSlice<d, T>(dir_fixed, index, this->coefs(), sizes, coefs);
158  }
159  else
160  {
161  // clone the basis and inserting up to degree knots at par
162  gsTensorBSpline<d,T>* clone = this->clone().release();
163 
164  gsVector<index_t,d> intStrides;
165  this->basis().stride_cwise(intStrides);
167  clone->basis().knots(dir_fixed),clone->coefs(),par,dir_fixed,
168  intStrides.template cast<unsigned>(), degree-mult,true);
169 
170  // extract right ceofficients
171  const gsKnotVector<T>& knots = clone->basis().knots(dir_fixed);
172  if (par == *knots.domainEnd())
173  index = knots.size()-clone->basis().degree(dir_fixed)-2;
174  else
175  index = (knots.iFind(par) - knots.begin()) - clone->basis().degree(dir_fixed);
176  gsVector<index_t,d> sizes;
177  clone->basis().size_cwise(sizes);
178  constructCoefsForSlice<d, T>(dir_fixed, index, clone->coefs(), sizes, coefs);
179  delete clone;
180  }
181 
182  // construct the object
183  //result = gsTensorBSpline<static_cast<short_t>(d-1),T>(*tbasis, give(coefs) );
184  //result = BoundaryGeometry(*tbasis, give(coefs) );
185  result = BoundaryGeometryType(*tbasis, coefs );
186  }
187 }
188 
189 template<short_t d, class T>
191 {
192  gsTensorBSplineBasis<d,T> & tbsbasis = this->basis();
194  tbsbasis.size_cwise(sz);
195  flipTensorVector(k, sz, m_coefs);
196  tbsbasis.component(k).reverse();
197 }
198 
199 
200 template<short_t d, class T>
201 void gsTensorBSpline<d,T>::swapDirections(const unsigned i, const unsigned j)
202 {
204  this->basis().size_cwise(sz);
205  swapTensorDirection(i, j, sz, m_coefs);
206  this->basis().swapDirections(i,j);
207 }
208 
209 template<short_t d, class T>
211 {
212  swapDirections(0,1);
213 }
214 
215 
216 template<short_t d, class T>
218 {
219  gsVector<index_t,d> str(d), vupp(d), curr = gsVector<index_t,d>::Zero(d);
220  this->basis().stride_cwise(str);
221  this->basis().size_cwise(vupp);
222  vupp.array() -= 1;
223 
224  do // loop over all vertices
225  {
226  if ( (v - m_coefs.row(curr.dot(str))).squaredNorm() < tol )
227  return true;
228  }
229  while ( nextCubeVertex(curr, vupp) );
230 
231  return false;
232 }
233 
234 template<short_t d, class T>
236  gsVector<index_t,d> & curr,
237  T tol)
238 {
239  gsVector<index_t,d> str , // Tensor strides
240  vupp; // Furthest corner
241 
242  this->basis().stride_cwise(str);
243  this->basis().size_cwise(vupp);
244  vupp.array() -= 1;
245 
246  curr.setZero();
247  do // loop over all vertices
248  {
249  if ( (v - m_coefs.row(curr.dot(str))).squaredNorm() < tol )
250  return;
251  }
252  while ( nextCubeVertex(curr, vupp) );
253 
254  // Corner not found, Invalidate the result
255  vupp.array() += 1;
256  curr.swap(vupp);
257  gsWarn<<"Point "<< v <<" is not an corner of the patch. (Call isPatchCorner() first!).\n";
258 }
259 
260 template<short_t d, class T>
262 {
263  gsVector<index_t,d> curr;
264  findCorner(v, curr);
265  if ( curr[0] == this->basis().size(0) )
266  return;
267  for(unsigned k = 0; k!=d; ++k)
268  if ( curr[k] != 0 )
269  this->reverse(k);
270 }
271 
272 template<short_t d, class T>
274 {
275  gsVector<index_t,d> curr;
276  findCorner(v, curr);
277  if ( curr[0] == this->basis().size(0) )
278  return;
279  for(unsigned k = 0; k!=d; ++k)
280  if ( curr[k] == 0 )
281  this->reverse(k);
282 }
283 
284 
285 template<short_t d, class T>
287 {
288  if (dir == -1)
289  {
290  for (short_t j = 0; j < d; ++j)
291  degreeElevate(i, j);
292  return;
293  }
294 
295  GISMO_ASSERT( dir >= 0 && static_cast<unsigned>(dir) < d,
296  "Invalid basis component "<< dir <<" requested for degree elevation" );
297 
298  const index_t n = this->m_coefs.cols();
299 
301  this->basis().size_cwise(sz);
302 
303  swapTensorDirection(0, dir, sz, this->m_coefs);
304  this->m_coefs.resize( sz[0], n * sz.template tail<static_cast<short_t>(d-1)>().prod() );
305 
306  bspline::degreeElevateBSpline(this->basis().component(dir), this->m_coefs, i);
307  sz[0] = this->m_coefs.rows();
308 
309  this->m_coefs.resize( sz.prod(), n );
310  swapTensorDirection(0, dir, sz, this->m_coefs);
311 }
312 
313 template<short_t d, class T>
314 void gsTensorBSpline<d,T>::insertKnot( T knot, int dir, int i)
315 {
316  GISMO_ASSERT( i>0, "multiplicity must be at least 1");
317 
318 
319  GISMO_ASSERT( dir >= 0 && static_cast<unsigned>(dir) < d,
320  "Invalid basis component "<< dir <<" requested for degree elevation" );
321 
322  const index_t n = this->m_coefs.cols();
323 
325  this->basis().size_cwise(sz);
326 
327  swapTensorDirection(0, dir, sz, this->m_coefs);
328  this->m_coefs.resize( sz[0], n * sz.template tail<static_cast<short_t>(d-1)>().prod() );
329 
330  gsBoehm( this->basis().component(dir).knots(), this->coefs() , knot, i);
331  sz[0] = this->m_coefs.rows();
332 
333  this->m_coefs.resize( sz.prod(), n );
334  swapTensorDirection(0, dir, sz, this->m_coefs);
335 }
336 
337 
338 template<short_t d, class T>
340 {
341  std::vector<KnotVectorType> kv(d); // the local knot-vectors
342  gsVector<index_t,d> cfirst, clast; // tensor-indices of local coefficients
343  index_t sz = 1; // number of control points in the local representation
344 
345  // Fill in the data defined above
346  for(unsigned i = 0; i!=d; ++i)
347  {
348  const int deg = degree(i);
349  typename KnotVectorType::const_iterator span = knots(i).iFind(u(i,0));
350 
351  sz *= deg + 1;
352  clast[i] = span - knots(i).begin();
353  cfirst[i] = clast[i] - deg;
354  kv[i] = KnotVectorType(deg, span - deg, span + deg + 2);
355  }
356 
357  // Collect the local coefficients
358  const gsMatrix<T> & allCoefs = this->coefs();
359  gsMatrix<T> coefs(sz, allCoefs.cols() );
360  gsVector<index_t,d> str, cur = cfirst;
361  basis().stride_cwise(str);
362  index_t r = 0;
363  do {
364  coefs.row(r++) = allCoefs.row( cur.dot(str) );
365  } while ( nextCubePoint(cur, cfirst, clast) );
366 
367  // All set, return the local representation
368  return Basis(kv).makeGeometry(give(coefs));
369 }
370 
371 
372 template<short_t d, class T>
373 std::ostream & gsTensorBSpline<d,T>::print(std::ostream &os) const
374 {
375  os << "Tensor BSpline geometry "<< "R^"<< d <<
376  " --> R^"<< this->geoDim()
377  << ", #control pnts= "<< this->coefsSize();
378  if ( m_coefs.size() )
379  os << ": "<< this->coef(0) <<" ... "<< this->coef(this->coefsSize()-1);
380  if ( m_basis )
381  os<<"\nBasis:\n" << this->basis() ;
382  return os;
383 }
384 
385 template<short_t d, class T>
386 std::vector<gsGeometry<T>* > gsTensorBSpline<d,T>::uniformSplit(index_t dir) const
387 {
388  // 1. insert p+1 in all directions
389  // 2. recover 2^d patches
390  GISMO_ASSERT( (dir > -2) && (dir < static_cast<index_t>(d)),
391  "Invalid basis component "<< dir <<" requested for geometry splitting" );
392  std::vector<gsGeometry<T>* > result_temp, result;
393  gsVector<T> midpoints;
394  if(dir==-1)
395  {
396  result.reserve(math::exp2(d));
397  midpoints.setZero(d);
398 
399  for(unsigned i=0; i<d;++i)
400  midpoints(i)= (basis().knots(i).sbegin().value() + (--basis().knots(i).send()).value())/ (T)(2);
401 
402  for(unsigned i=0; i<d;++i)
403  {
404  result_temp.clear();
405 
406  //one could uniform the if-statement and the for-loop by setting result[0] = this,
407  //however, the const prevents this.
408  if(result.size()==0)
409  {
412  this->splitAt(i,midpoints(i),*left,*right);
413  result_temp.push_back(left);
414  result_temp.push_back(right);
415  }
416  for(size_t j=0; j<result.size();j++)
417  {
420  static_cast<gsTensorBSpline<d,T>*>(result[j])->splitAt(i,midpoints(i),*left,*right);
421 
422  result_temp.push_back(left);
423  result_temp.push_back(right);
424  }
425 
426 
427  freeAll(result);
428  result = result_temp;
429  }
430  }
431  else
432  {
433  result.reserve(2);
434  T xi = (basis().knots(dir).sbegin().value() + (--basis().knots(dir).send()).value())/(T)(2);
437 
438  splitAt(dir,xi,*left,*right);
439 
440  result.push_back(left);
441  result.push_back(right);
442  }
443  return result;
444 
445 }
446 
447 
448 template<short_t d, class T>
450 {
451  GISMO_ASSERT( (dir >= 0) && (dir < static_cast<index_t>(d)),
452  "Invalid basis component "<< dir <<" requested for geometry splitting" );
453 
454  GISMO_ASSERT(basis().knots(dir).sbegin().value()<xi && xi< (--basis().knots(dir).send()).value() , "splitting point "<<xi<<" not in the knotvector");
455 
456  //First make a copy of the actual object, to allow const
457  gsTensorBSpline<d,T> copy(*this);
458 
459  // Extract a reference to the knots, the basis and coefs of the copy
460  KnotVectorType & knots = copy.basis().knots(dir);
461  gsTensorBSplineBasis<d,T> & base = copy.basis();
462 
463  // some constants
464  const int p = base.degree(dir); // degree
465  const index_t mult = p + 1 - knots.multiplicity(xi); // multiplicity
466 
467  //insert the knot, such that its multiplicity is p+1
468  if (mult>0)
469  copy.insertKnot(xi, dir, mult);
470 
471  //swap the direction dir with 0, to be able to extract the coefs.
472  copy.swapDirections(0,dir);
473 
474  gsMatrix<T> & coefs = copy.coefs();
475  const index_t tDim = coefs.cols();
476 
477  //some more constants
478  gsVector<index_t,d> sizes; // number of coefs in each dir
479  base.size_cwise(sizes);
480  const index_t sz = sizes.prod(); // total number of coefs
481 
482  //find the number of coefs left from xi (in direction 0)
483  const index_t nL = knots.uFind(xi).firstAppearance();
484  index_t nR = base.size(0) - nL;
485 
486  //Split the coefficients
487  gsMatrix<T> coefL, coefR;
488  coefL.setZero(sizes.tail(d-1).prod()*(nL), tDim);
489  coefR.setZero(sz-coefL.rows(), tDim);
490 
491  index_t kL,kR,i;
492  i=kL=kR=0;
493  while(i<sz)
494  {
495  coefL.block(kL,0,nL, tDim) = coefs.block(i,0,nL, tDim);
496  coefR.block(kR,0,nR, tDim) = coefs.block(i+nL,0,nR, tDim);
497 
498  kL+=nL;
499  kR+=nR;
500 
501  i+= nL + nR;
502  }
503 
504  //build up the new geometries
505  //build the knot vector for direction 0 (swapped!)
506  typename KnotVectorType::iterator it = knots.iFind(xi);
507  typename KnotVectorType::knotContainer matL(knots.begin(),++it);
508  it-=p+1; // move the iterator to the beginning of the inserted knots
509  typename KnotVectorType::knotContainer matR(it, knots.end());
510  KnotVectorType knotsL(give(matL),p);
511  KnotVectorType knotsR(give(matR),p);
512 
513  // rescale the splitted knot vector (not mandatory)
514  // knotsL.affineTransformTo(0,1);
515  // knotsR.affineTransformTo(0,1);
516 
517  //collect the other directions
518  std::vector<KnotVectorType> KVL, KVR;
519  KVL.push_back(knotsL);
520  KVR.push_back(knotsR);
521  for(i=1; i<static_cast<index_t>(d);++i)
522  {
523  KVL.push_back(base.knots(i));
524  KVR.push_back(base.knots(i));
525  }
526 
527  //finally the two new geometries
528  left = gsTensorBSpline<d,T>(Basis(give(KVL)), give(coefL));
529  left.swapDirections(0,dir);
530  right = gsTensorBSpline<d,T>(Basis(give(KVR)), give(coefR));
531  right.swapDirections(0,dir);
532 }
533 
534 
535 template<short_t d, class T>
536 std::vector<gsGeometry<T>* >
538 {
539  GISMO_ASSERT( (dir >= -1) && (dir < static_cast<index_t>(d)),
540  "Invalid basis component "<< dir <<" requested for splitting" );
541  std::vector<gsGeometry<T>* > result;
542 
543  if (-1==dir)
544  {
545  std::vector<gsGeometry<T>* > tmpi, tmp;
546  result = this->splitAtMult(minMult,0);
547  for(short_t i=1; i<d;++i)
548  {
549  tmp.swap(result);
550  result.clear();
551  for(size_t j=0; j!=tmp.size();++j)
552  {
553  tmpi = static_cast<gsTensorBSpline<d,T>*>(tmp[j])
554  ->splitAtMult(minMult,i);
555  delete tmp[j];
556  result.insert( result.end(), tmpi.begin(), tmpi.end() );
557  }
558  }
559  return result;
560  }
561 
562  gsTensorBSpline<d,T> * tmp = new gsTensorBSpline<d,T>(*this);
563  //iterate over knots
564  for (typename KnotVectorType::uiterator it = knots(dir).ubegin()+1;
565  it!=knots(dir).uend()-1; ++it)
566  {
567  if (it.multiplicity()>=minMult)
568  {
570  tmp->splitAt(dir,*it,*o,*tmp);
571  result.push_back(o);
572  }
573  }
574  result.push_back(tmp);
575  return result;
576 }
577 
578 
579 template<short_t d, class T>
580 typename gsGeometry<T>::uPtr
582  const gsGeometry<T> & other) const
583 {
584  // Grab boundary control point indices in matching configuration
585  gsMatrix<index_t> bdr0, bdr1;
586  this->basis().matchWith(bi, other.basis(), bdr0, bdr1);
587 
588  //from here: Assume linear curves, merge control points (todo: add option for this)
589  index_t b[2];
590  b[0]=b[1]=0;
591  std::list<std::pair<const gsMatrix<T> *,index_t> > cv;//patch,cp-index
592  //maybe: check if both ifaces are identical using a flag...
593 
594  cv.push_back( std::make_pair(&this->coefs(), bdr0.at(b[0]++) ) );
595  do {
596  T dist0=(cv.back().first->row(cv.back().second)-this->coef(bdr0.at(b[0]))).squaredNorm();
597  if ( 0 == dist0 ) { b[0]++; continue; } //skip double point
598  T dist1=(cv.back().first->row(cv.back().second)-other.coef(bdr1.at(b[1]))).squaredNorm();
599  if ( 0 == dist1 ) { b[1]++; continue; } //skip double point
600 
601  // gsDebugVar(dist0);
602  // gsDebugVar(dist1);
603  // gsDebugVar( this->coef(bdr0.at(b[0]+1)) );
604  // gsDebugVar( other.coef(bdr1.at(b[1])) );
605  if (dist0>dist1)
606  cv.push_back( std::make_pair(&other.coefs(), bdr1.at(b[1]++) ) );
607  else
608  cv.push_back( std::make_pair(&this->coefs(), bdr0.at(b[0]++) ) );
609 
610  } while ( b[0]!=bdr0.size() && b[1]!=bdr1.size() );
611 
612  //gsDebugVar(cv.size());
613  while ( b[0]<bdr0.size() )
614  cv.push_back( std::make_pair(&this->coefs(), bdr0.at(b[0]++) ) );
615 
616  //gsDebugVar(cv.size());
617  while ( b[1]<bdr1.size() )
618  cv.push_back( std::make_pair(&other.coefs(), bdr1.at(b[1]++) ) );
619 
620  //gsDebugVar(cv.size());
621 
622  // temporary fix: the last point is always doubled.
623  cv.pop_back();
624 
625  // Construct interface geometry using cv and uniform knots (polyline)
626  gsMatrix<T> cf(cv.size(),this->geoDim());
627  index_t c = 0;
628  for(typename std::list<std::pair<const gsMatrix<T> *,index_t> >::iterator
629  it = cv.begin(); it!=cv.end(); ++it)
630  cf.row(c++) = it->first->row(it->second);
631  gsKnotVector<T> kv(0,1,c-2,2,1);
632  gsBSplineBasis<T> bs(kv);
633  return bs.makeGeometry(cf);
634 }
635 
636 
637 namespace internal
638 {
639 
643 template<short_t d, class T>
644 class gsXml< gsTensorBSpline<d,T> >
645 {
646 private:
647  gsXml() { }
648 public:
649  GSXML_COMMON_FUNCTIONS(gsTensorBSpline<TMPLA2(d,T)>);
650  static std::string tag () { return "Geometry"; }
651  static std::string type () { return "TensorBSpline" + to_string(d); }
652 
653  static gsTensorBSpline<d,T> * get (gsXmlNode * node)
654  {
655  return getGeometryFromXml< gsTensorBSpline<d,T> >( node );
656  }
657 
658  static gsXmlNode * put (const gsTensorBSpline<d,T> & obj,
659  gsXmlTree & data)
660  {
661  return putGeometryToXml(obj,data);
662  }
663 };
664 
665 
666 
667 }// namespace internal
668 
669 } // namespace gismo
void gsBoehm(KnotVectorType &knots, Mat &coefs, T val, int r=1, bool update_knots=true)
Performs insertion of multiple knot on &quot;knots&quot; and coefficients &quot;coefs&quot;.
Definition: gsBoehm.hpp:29
short_t degree(short_t i) const
Returns the degree of the basis wrt variable i.
Definition: gsTensorBasis.h:465
Abstract base class representing a geometry map.
Definition: gsGeometry.h:92
gsMatrix< T >::RowXpr coef(index_t i)
Returns the i-th coefficient of the geometry as a row expression.
Definition: gsGeometry.h:346
void reverse(unsigned k)
Definition: gsTensorBSpline.hpp:190
void swapDirections(const unsigned i, const unsigned j)
Swap directions.
Definition: gsTensorBSpline.hpp:201
std::vector< gsGeometry< T > * > uniformSplit(index_t dir=-1) const
Definition: gsTensorBSpline.hpp:386
index_t size() const
Returns the number of elements in the basis.
Definition: gsTensorBasis.h:108
gsTensorBSpline()
Default empty constructor.
Definition: gsTensorBSpline.h:73
bool isPatchCorner(gsMatrix< T > const &v, T tol=1e-3) const
Return true if point u is a corner of the patch with tolerance tol.
Definition: gsTensorBSpline.hpp:217
bool nextCubePoint(Vec &cur, const Vec &end)
Iterate in lexigographic order through the points of the integer lattice contained in the cube [0...
Definition: gsCombinatorics.h:327
#define short_t
Definition: gsConfig.h:35
A tensor product of d B-spline functions, with arbitrary target dimension.
Definition: gsTensorBSpline.h:44
void insertKnot(T knot, int dir, int i=1)
Inserts knot knot at direction dir, i times.
Definition: gsTensorBSpline.hpp:314
void splitAt(index_t dir, T xi, gsTensorBSpline< d, T > &left, gsTensorBSpline< d, T > &right) const
Definition: gsTensorBSpline.hpp:449
iterator domainEnd() const
Returns an iterator pointing to the end-knot of the domain.
Definition: gsKnotVector.h:342
Provides declaration of ConstantFunction class.
Boehm&#39;s algorithm for knot insertion.
void swapTensorDirection(int k1, int k2, gsVector< index_t, d > &sz, gsMatrix< T > &coefs)
Definition: gsTensorTools.h:129
gsGeometry< T >::uPtr localRep(const gsMatrix< T > &u) const
Definition: gsTensorBSpline.hpp:339
Utility functions related to tensor-structured objects.
S give(S &x)
Definition: gsMemory.h:266
void flipTensorVector(const int dir, const gsVector< index_t, d > &sz, gsMatrix< T > &coefs)
Flips tensor directions in place.
Definition: gsTensorTools.h:201
size_t size() const
Number of knots (including repetitions).
Definition: gsKnotVector.h:242
#define index_t
Definition: gsConfig.h:32
void size_cwise(gsVector< index_t, s > &result) const
The number of basis functions in the direction of the k-th parameter component.
Definition: gsTensorBasis.h:441
void tensorStrides(const VectIn &sz, VectOut &strides)
Helper to compute the strides of a d-tensor.
Definition: gsTensorTools.h:115
A tensor product B-spline basis.
Definition: gsTensorBSplineBasis.h:36
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
gsXmlNode * putGeometryToXml(Object const &obj, gsXmlTree &data)
Helper to put geometries to XML.
Definition: gsXmlGenericUtils.hpp:388
Provides implementation of generic XML functions.
iterator iFind(const T u) const
Returns an iterator to the last occurrence of the knot at the beginning of the knot interval containi...
Definition: gsKnotVector.hpp:779
A univariate B-spline basis.
Definition: gsBSplineBasis.h:694
void degreeElevateBSpline(Basis_t &basis, gsMatrix< typename Basis_t::Scalar_t > &coefs, short_t m)
Increase the degree of a 1D B-spline from degree p to degree p + m.
Definition: gsBSplineAlgorithms.h:224
Implementation of common algorithms for B-splines.
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition: gsMatrix.h:211
std::string to_string(const unsigned &i)
Helper to convert small unsigned to string.
Definition: gsXml.cpp:74
#define gsWarn
Definition: gsDebug.h:50
std::vector< gsGeometry< T > * > splitAtMult(index_t minMult=1, index_t dir=-1) const
Definition: gsTensorBSpline.hpp:537
virtual memory::unique_ptr< gsGeometry< T > > makeGeometry(gsMatrix< T > coefs) const =0
Create a gsGeometry of proper type for this basis with the given coefficient matrix.
void freeAll(It begin, It end)
Frees all pointers in the range [begin end)
Definition: gsMemory.h:312
Struct which represents a certain side of a box.
Definition: gsBoundary.h:84
void findCorner(const gsMatrix< T > &v, gsVector< index_t, d > &curr, T tol=1e-3)
returns the tensor-index curr of the corner control point v, or an invalid index if the corner is not...
Definition: gsTensorBSpline.hpp:235
void setFurthestCorner(gsMatrix< T > const &v)
Modifies the parameterization such that the point v is the ending corner of the parametrization of th...
Definition: gsTensorBSpline.hpp:273
void slice(index_t dir_fixed, T par, BoundaryGeometryType &result) const
Definition: gsTensorBSpline.hpp:125
memory::unique_ptr< gsGeometry > uPtr
Unique pointer for gsGeometry.
Definition: gsGeometry.h:100
Represents a B-spline curve/function with one parameter.
void degreeElevate(short_t const i=1, short_t const dir=-1)
Elevate the degree by the given amount i for the direction dir. If dir is -1 then degree elevation is...
Definition: gsTensorBSpline.hpp:286
memory::unique_ptr< Self_t > uPtr
Smart pointer for gsTensorBSplineBasis.
Definition: gsTensorBSplineBasis.h:69
bool nextLexicographic(Vec &cur, const Vec &size)
Iterates through a tensor lattice with the given size. Updates cur and returns true if another entry ...
Definition: gsCombinatorics.h:196
Class for representing a knot vector.
Definition: gsKnotVector.h:79
void setOriginCorner(gsMatrix< T > const &v)
Modifies the parameterization such that the point v is the origin of the parametrization of the patch...
Definition: gsTensorBSpline.hpp:261
Struct which represents an interface between two patches.
Definition: gsBoundary.h:649
iterator begin() const
Returns iterator pointing to the beginning of the repeated knots.
Definition: gsKnotVector.hpp:117
void gsTensorBoehm(KnotVectorType &knots, Mat &coefs, T val, int direction, gsVector< unsigned > str, int r=1, bool update_knots=true)
Definition: gsBoehm.hpp:245
const Basis_t & component(short_t dir) const
For a tensor product basis, return the (const) 1-d basis for the i-th parameter component.
Definition: gsTensorBSplineBasis.h:202
virtual const gsBasis< T > & basis() const =0
Returns a const reference to the basis of the geometry.
void constructCoefsForSlice(index_t dir_fixed, const index_t index, const gsMatrix< T > &fullCoefs, const gsVector< index_t, d > &sizes, gsMatrix< T > &result)
Definition: gsTensorBSpline.hpp:32
std::ostream & print(std::ostream &os) const
Prints the object as a string.
Definition: gsTensorBSpline.hpp:373
Provides declaration of input/output XML utilities struct.
gsMatrix< T > & coefs()
Definition: gsGeometry.h:340
void copy(T begin, T end, U *result)
Small wrapper for std::copy mimicking std::copy for a raw pointer destination, copies n positions sta...
Definition: gsMemory.h:391
bool nextCubeVertex(Vec &cur, const Vec &start, const Vec &end)
Iterate in lexicographic order through the vertices of the cube [start,end]. Updates cur with the cur...
Definition: gsCombinatorics.h:252