G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
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
27
28namespace gismo
29{
30
31template<short_t d, class T>
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
54template<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 }
118
119 this->m_basis = tbasis;
120 this->m_coefs.swap( pcp );
121}
122
123// todo: move to hpp
124template<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);
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);
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
189template<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
200template<short_t d, class T>
201void 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
209template<short_t d, class T>
211{
212 swapDirections(0,1);
213}
214
215
216template<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) );
231 return false;
232}
233
234template<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";
259
260template<short_t d, class T>
262{
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
272template<short_t d, class T>
274{
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
285template<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
313template<short_t d, class T>
314void 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
338template<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
372template<short_t d, class T>
373std::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
385template<short_t d, class T>
386std::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
448template<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
535template<short_t d, class T>
536std::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
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
579template<short_t d, class T>
580typename 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
637namespace internal
638{
639
643template<short_t d, class T>
644class gsXml< gsTensorBSpline<d,T> >
645{
646private:
647 gsXml() { }
648public:
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
Struct which represents a certain side of a box.
Definition gsBoundary.h:85
A univariate B-spline basis.
Definition gsBSplineBasis.h:700
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.
Abstract base class representing a geometry map.
Definition gsGeometry.h:93
gsMatrix< T > & coefs()
Definition gsGeometry.h:340
gsMatrix< T >::RowXpr coef(index_t i)
Returns the i-th coefficient of the geometry as a row expression.
Definition gsGeometry.h:346
memory::unique_ptr< gsGeometry > uPtr
Unique pointer for gsGeometry.
Definition gsGeometry.h:100
virtual const gsBasis< T > & basis() const =0
Returns a const reference to the basis of the geometry.
Class for representing a knot vector.
Definition gsKnotVector.h:80
size_t size() const
Number of knots (including repetitions).
Definition gsKnotVector.h:242
iterator begin() const
Returns iterator pointing to the beginning of the repeated knots.
Definition gsKnotVector.hpp:117
iterator domainEnd() const
Returns an iterator pointing to the end-knot of the domain.
Definition gsKnotVector.h:342
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 matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
T at(index_t i) const
Returns the i-th element of the vectorization of the matrix.
Definition gsMatrix.h:211
A tensor product B-spline basis.
Definition gsTensorBSplineBasis.h:37
memory::unique_ptr< Self_t > uPtr
Smart pointer for gsTensorBSplineBasis.
Definition gsTensorBSplineBasis.h:69
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
A tensor product of d B-spline functions, with arbitrary target dimension.
Definition gsTensorBSpline.h:45
void swapDirections(const unsigned i, const unsigned j)
Swap directions.
Definition gsTensorBSpline.hpp:201
void insertKnot(T knot, int dir, int i=1)
Inserts knot knot at direction dir, i times.
Definition gsTensorBSpline.hpp:314
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
void reverse(unsigned k)
Definition gsTensorBSpline.hpp:190
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
void splitAt(index_t dir, T xi, gsTensorBSpline< d, T > &left, gsTensorBSpline< d, T > &right) const
Definition gsTensorBSpline.hpp:449
std::vector< gsGeometry< T > * > uniformSplit(index_t dir=-1) const
Definition gsTensorBSpline.hpp:386
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 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 slice(index_t dir_fixed, T par, BoundaryGeometryType &result) const
Definition gsTensorBSpline.hpp:125
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
std::ostream & print(std::ostream &os) const
Prints the object as a string.
Definition gsTensorBSpline.hpp:373
std::vector< gsGeometry< T > * > splitAtMult(index_t minMult=1, index_t dir=-1) const
Definition gsTensorBSpline.hpp:537
gsGeometry< T >::uPtr localRep(const gsMatrix< T > &u) const
Definition gsTensorBSpline.hpp:339
gsTensorBSpline()
Default empty constructor.
Definition gsTensorBSpline.h:73
short_t degree(short_t i) const
Returns the degree of the basis wrt variable i.
Definition gsTensorBasis.h:465
index_t size() const
Returns the number of elements in the basis.
Definition gsTensorBasis.h:108
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
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
void gsTensorBoehm(KnotVectorType &knots, Mat &coefs, T val, int direction, gsVector< unsigned > str, int r=1, bool update_knots=true)
Definition gsBoehm.hpp:245
void swapTensorDirection(int k1, int k2, gsVector< index_t, d > &sz, gsMatrix< T > &coefs)
Definition gsTensorTools.h:129
void flipTensorVector(const int dir, const gsVector< index_t, d > &sz, gsMatrix< T > &coefs)
Flips tensor directions in place.
Definition gsTensorTools.h:201
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
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
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
Implementation of common algorithms for B-splines.
Represents a B-spline curve/function with one parameter.
Boehm's algorithm for knot insertion.
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
Provides declaration of ConstantFunction class.
#define gsWarn
Definition gsDebug.h:50
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Utility functions related to tensor-structured objects.
Provides implementation of generic XML functions.
Provides declaration of input/output XML utilities struct.
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
gsXmlNode * putGeometryToXml(Object const &obj, gsXmlTree &data)
Helper to put geometries to XML.
Definition gsXmlGenericUtils.hpp:388
std::string to_string(const unsigned &i)
Helper to convert small unsigned to string.
Definition gsXml.cpp:74
The G+Smo namespace, containing all definitions for the library.
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
void gsBoehm(KnotVectorType &knots, Mat &coefs, T val, int r=1, bool update_knots=true)
Performs insertion of multiple knot on "knots" and coefficients "coefs".
Definition gsBoehm.hpp:29
void tensorStrides(const VectIn &sz, VectOut &strides)
Helper to compute the strides of a d-tensor.
Definition gsTensorTools.h:115
S give(S &x)
Definition gsMemory.h:266
void freeAll(It begin, It end)
Frees all pointers in the range [begin end)
Definition gsMemory.h:312
Struct which represents an interface between two patches.
Definition gsBoundary.h:650