31 template<
short_t d,
class T>
38 lowerCorner.setZero();
40 lowerCorner[dir_fixed] = index;
41 upperCorner[dir_fixed] = index + 1;
45 result.resize( sizes.prod() / sizes[dir_fixed], fullCoefs.cols() );
50 result.row(r++) = fullCoefs.row( cur.dot(str) );
54 template<
short_t d,
class T>
56 KnotVectorType KV1, KnotVectorType KV2)
58 GISMO_ASSERT(d==2,
"Wrong dimension: tried to make a "<< d<<
"D tensor B-spline using 2 knot-vectors.");
60 std::vector<Family_t*> cbases;
61 const int n1 = KV1.size() - KV1.degree() - 1;
62 const int n2 = KV2.size() - KV2.degree() - 1;
66 Basis * tbasis = Basis::New(cbases);
70 "gsTensorBSpline: Please make sure that the size of *corner* is 4-by-3");
76 for (
int i=0; i<=n1-1; i++)
78 for (
unsigned int xi=0; xi<=2; xi++)
80 pcp(i+j*n1,xi)=corner(0,xi) + i/((T)(n1-1))*( corner(1,xi) - corner(0,xi) );
84 for (
int i=0; i<=n1-1; i++)
86 for (
unsigned int xi=0; xi<=2; xi++)
88 pcp(i+j*n1,xi)=corner(3,xi) + i/((T)(n1-1))*( corner(2,xi) - corner(3,xi) );
92 for (j=0; j<=n2-1; j++)
94 for (
unsigned int xi=0; xi<=2; xi++)
96 pcp(i+j*n1,xi)=corner(0,xi) + j/((T)(n2-1))*( corner(3,xi) - corner(0,xi) );
100 for (j=0; j<=n2-1; j++)
102 for (
unsigned int xi=0; xi<=2; xi++)
104 pcp(i+j*n1,xi)=corner(1,xi) + j/((T)(n2-1))*( corner(2,xi) - corner(1,xi) );
108 for (j=1; j<=n2-2; j++)
110 for (i=1; i<=n1-2; i++)
112 for (
unsigned int xi=0; xi<=2; xi++)
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) );
119 this->m_basis = tbasis;
120 this->m_coefs.swap( pcp );
124 template<
short_t d,
class T>
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");
138 this->eval_into(val,point);
143 const int mult = this->basis().knots(dir_fixed).multiplicity(par);
144 const int degree = this->basis().degree(dir_fixed);
152 index = knots.
size()-this->basis().degree(dir_fixed)-2;
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);
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);
173 index = knots.
size()-clone->
basis().degree(dir_fixed)-2;
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);
189 template<
short_t d,
class T>
200 template<
short_t d,
class T>
204 this->basis().size_cwise(sz);
206 this->basis().swapDirections(i,j);
209 template<
short_t d,
class T>
216 template<
short_t d,
class T>
220 this->basis().stride_cwise(str);
221 this->basis().size_cwise(vupp);
226 if ( (v - m_coefs.row(curr.dot(str))).squaredNorm() < tol )
234 template<
short_t d,
class T>
242 this->basis().stride_cwise(str);
243 this->basis().size_cwise(vupp);
249 if ( (v - m_coefs.row(curr.dot(str))).squaredNorm() < tol )
257 gsWarn<<
"Point "<< v <<
" is not an corner of the patch. (Call isPatchCorner() first!).\n";
260 template<
short_t d,
class T>
265 if ( curr[0] == this->basis().size(0) )
267 for(
unsigned k = 0; k!=d; ++k)
272 template<
short_t d,
class T>
277 if ( curr[0] == this->basis().size(0) )
279 for(
unsigned k = 0; k!=d; ++k)
285 template<
short_t d,
class T>
290 for (
short_t j = 0; j < d; ++j)
295 GISMO_ASSERT( dir >= 0 && static_cast<unsigned>(dir) < d,
296 "Invalid basis component "<< dir <<
" requested for degree elevation" );
298 const index_t n = this->m_coefs.cols();
301 this->basis().size_cwise(sz);
304 this->m_coefs.resize( sz[0], n * sz.template tail<static_cast<short_t>(d-1)>().prod() );
307 sz[0] = this->m_coefs.rows();
309 this->m_coefs.resize( sz.prod(), n );
313 template<
short_t d,
class T>
319 GISMO_ASSERT( dir >= 0 && static_cast<unsigned>(dir) < d,
320 "Invalid basis component "<< dir <<
" requested for degree elevation" );
322 const index_t n = this->m_coefs.cols();
325 this->basis().size_cwise(sz);
328 this->m_coefs.resize( sz[0], n * sz.template tail<static_cast<short_t>(d-1)>().prod() );
330 gsBoehm( this->basis().component(dir).knots(), this->coefs() , knot, i);
331 sz[0] = this->m_coefs.rows();
333 this->m_coefs.resize( sz.prod(), n );
338 template<
short_t d,
class T>
341 std::vector<KnotVectorType> kv(d);
346 for(
unsigned i = 0; i!=d; ++i)
348 const int deg = degree(i);
349 typename KnotVectorType::const_iterator span = knots(i).iFind(u(i,0));
352 clast[i] = span - knots(i).begin();
353 cfirst[i] = clast[i] - deg;
354 kv[i] = KnotVectorType(deg, span - deg, span + deg + 2);
361 basis().stride_cwise(str);
364 coefs.row(r++) = allCoefs.row( cur.dot(str) );
372 template<
short_t d,
class T>
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);
381 os<<
"\nBasis:\n" << this->basis() ;
385 template<
short_t d,
class T>
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;
396 result.reserve(math::exp2(d));
397 midpoints.setZero(d);
399 for(
unsigned i=0; i<d;++i)
400 midpoints(i)= (basis().knots(i).sbegin().value() + (--basis().knots(i).send()).value())/ (T)(2);
402 for(
unsigned i=0; i<d;++i)
412 this->splitAt(i,midpoints(i),*left,*right);
413 result_temp.push_back(left);
414 result_temp.push_back(right);
416 for(
size_t j=0; j<result.size();j++)
422 result_temp.push_back(left);
423 result_temp.push_back(right);
428 result = result_temp;
434 T xi = (basis().knots(dir).sbegin().value() + (--basis().knots(dir).send()).value())/(T)(2);
438 splitAt(dir,xi,*left,*right);
440 result.push_back(left);
441 result.push_back(right);
448 template<
short_t d,
class T>
451 GISMO_ASSERT( (dir >= 0) && (dir < static_cast<index_t>(d)),
452 "Invalid basis component "<< dir <<
" requested for geometry splitting" );
454 GISMO_ASSERT(basis().knots(dir).sbegin().value()<xi && xi< (--basis().knots(dir).send()).value() ,
"splitting point "<<xi<<
" not in the knotvector");
460 KnotVectorType & knots = copy.
basis().knots(dir);
464 const int p = base.
degree(dir);
465 const index_t mult = p + 1 - knots.multiplicity(xi);
475 const index_t tDim = coefs.cols();
480 const index_t sz = sizes.prod();
483 const index_t nL = knots.uFind(xi).firstAppearance();
488 coefL.setZero(sizes.tail(d-1).prod()*(nL), tDim);
489 coefR.setZero(sz-coefL.rows(), tDim);
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);
506 typename KnotVectorType::iterator it = knots.iFind(xi);
507 typename KnotVectorType::knotContainer matL(knots.begin(),++it);
509 typename KnotVectorType::knotContainer matR(it, knots.end());
510 KnotVectorType knotsL(
give(matL),p);
511 KnotVectorType knotsR(
give(matR),p);
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)
523 KVL.push_back(base.knots(i));
524 KVR.push_back(base.knots(i));
535 template<
short_t d,
class T>
536 std::vector<gsGeometry<T>* >
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;
545 std::vector<gsGeometry<T>* > tmpi, tmp;
546 result = this->splitAtMult(minMult,0);
551 for(
size_t j=0; j!=tmp.size();++j)
554 ->splitAtMult(minMult,i);
556 result.insert( result.end(), tmpi.begin(), tmpi.end() );
564 for (
typename KnotVectorType::uiterator it = knots(dir).ubegin()+1;
565 it!=knots(dir).uend()-1; ++it)
567 if (it.multiplicity()>=minMult)
574 result.push_back(tmp);
579 template<
short_t d,
class T>
586 this->basis().matchWith(bi, other.
basis(), bdr0, bdr1);
591 std::list<std::pair<const gsMatrix<T> *,
index_t> > cv;
594 cv.push_back( std::make_pair(&this->coefs(), bdr0.
at(b[0]++) ) );
596 T dist0=(cv.back().first->row(cv.back().second)-this->coef(bdr0.
at(b[0]))).squaredNorm();
597 if ( 0 == dist0 ) { b[0]++;
continue; }
598 T dist1=(cv.back().first->row(cv.back().second)-other.
coef(bdr1.
at(b[1]))).squaredNorm();
599 if ( 0 == dist1 ) { b[1]++;
continue; }
606 cv.push_back( std::make_pair(&other.
coefs(), bdr1.
at(b[1]++) ) );
608 cv.push_back( std::make_pair(&this->coefs(), bdr0.
at(b[0]++) ) );
610 }
while ( b[0]!=bdr0.size() && b[1]!=bdr1.size() );
613 while ( b[0]<bdr0.size() )
614 cv.push_back( std::make_pair(&this->coefs(), bdr0.
at(b[0]++) ) );
617 while ( b[1]<bdr1.size() )
618 cv.push_back( std::make_pair(&other.
coefs(), bdr1.
at(b[1]++) ) );
626 gsMatrix<T> cf(cv.size(),this->geoDim());
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);
643 template<
short_t d,
class T>
644 class gsXml< gsTensorBSpline<d,T> >
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); }
653 static gsTensorBSpline<d,T> *
get (gsXmlNode * node)
655 return getGeometryFromXml< gsTensorBSpline<d,T> >( node );
658 static gsXmlNode * put (
const gsTensorBSpline<d,T> & obj,
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
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'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
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