G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsTensorNurbs.h
Go to the documentation of this file.
1
14#pragma once
15
16#include <gsCore/gsGeometry.h>
18
19#include <gsTensor/gsTensorTools.h> // todo: move to hpp
20
21namespace gismo
22{
23
39template<short_t d, class T>
40class gsTensorNurbs : public gsGeoTraits<d,T>::GeometryBase
41{
42
43public:
44 typedef gsKnotVector<T> KnotVectorType;
45
46 typedef typename gsGeoTraits<d,T>::GeometryBase Base;
47
48 typedef T Scalar_t;
49
50 typedef gsTensorBSplineBasis<d,T> TBasis; // underlying tensor basis
51
54
55 // rational version of tensor basis (basis for this geometry)
57
59 typedef typename gsBSplineTraits<static_cast<short_t>(d-1),T>::RatGeometry BoundaryGeometryType;
60 //typedef gsTensorNurbs<static_cast<short_t>(d-1),T> BoundaryGeometryType;
61
63 typedef typename gsBSplineTraits<static_cast<short_t>(d-1),T>::RatBasis BoundaryBasisType;
64
66 typedef memory::shared_ptr< gsTensorNurbs > Ptr;
67
69 typedef memory::unique_ptr< gsTensorNurbs > uPtr;
70
71public:
72
75
76 gsTensorNurbs( const Basis & basis, gsMatrix<T> coefs ) :
77 Base( basis, give(coefs) ) { }
78
82 gsMatrix<T> tcoefs)
83 {
84 GISMO_ASSERT(d==2, "Wrong dimension: tried to make a "<< d
85 <<"D NURBS using 2 knot-vectors.");
86
89
90 TBasis *tbasis = new TBasis(Bu,Bv) ;//d==2
91
92 this->m_basis = new Basis(tbasis) ;
93 this->m_coefs.swap(tcoefs);
94 GISMO_ASSERT(tbasis->size()== m_coefs.rows(),
95 "Coefficient matrix for the NURBS does not have "
96 "the expected number of control points (rows)." );
97 }
98
101 gsMatrix<T> tcoefs, gsMatrix<T> wgts)
102 {
103 GISMO_ASSERT(d==2, "Wrong dimension: tried to make a "<< d
104 <<"D NURBS using 2 knot-vectors.");
105
106 gsBSplineBasis<T> * Bu = new gsBSplineBasis<T>(KV1);
107 gsBSplineBasis<T> * Bv = new gsBSplineBasis<T>(KV2);
108
109 TBasis *tbasis = new TBasis(Bu,Bv) ;//d==2
110
111 GISMO_ASSERT(tbasis->size()== tcoefs.rows(),
112 "Coefficient matrix for the NURBS does not have "
113 "the expected number of control points (rows)." );
114
115 this->m_basis = new Basis(tbasis , give(wgts)) ;
116 this->m_coefs.swap(tcoefs);
117 }
118
122 gsKnotVector<T> const & KV2,
123 gsKnotVector<T> const & KV3,
124 gsMatrix<T> tcoefs,
125 gsMatrix<T> wgts )
126 {
127 GISMO_ASSERT(d==3, "Wrong dimension: tried to make a "<< d
128 <<"D NURBS using 3 knot-vectors.");
129
133 TBasis *tbasis = new TBasis(Bu,Bv,Bw) ;//d==3
134
135 GISMO_ASSERT(tbasis->size()== tcoefs.rows(),
136 "Coefficient matrix for the NURBS does not have "
137 "the expected number of control points (rows)." );
138
139 this->m_basis = new Basis(tbasis, give(wgts));
140 this->m_coefs.swap(tcoefs);
141 }
142
146 gsKnotVector<T> const & KV2,
147 gsKnotVector<T> const & KV3,
148 gsMatrix<T> tcoefs)
149 {
150 GISMO_ASSERT(d==3, "Wrong dimension: tried to make a "<< d
151 <<"D NURBS using 3 knot-vectors.");
152
156 TBasis *tbasis = new TBasis(Bu,Bv,Bw) ;//d==3
157
158 GISMO_ASSERT(tbasis->size()== tcoefs.rows(),
159 "Coefficient matrix for the NURBS does not have "
160 "the expected number of control points (rows)." );
161
162 this->m_basis = new Basis(tbasis) ;
163 this->m_coefs.swap(tcoefs);
164 }
165
169 gsKnotVector<T> const & KV2,
170 gsKnotVector<T> const & KV3,
171 gsKnotVector<T> const & KV4,
172 gsMatrix<T> tcoefs,
173 gsMatrix<T> wgts )
174 {
175 GISMO_ASSERT(d==4, "Wrong dimension: tried to make a "<< d
176 <<"D NURBS using 4 knot-vectors.");
177
178 std::vector< gsBSplineBasis<T>* > cbases;
179 cbases.reserve(4);
180 cbases.push_back(new gsBSplineBasis<T>(KV1) );
181 cbases.push_back(new gsBSplineBasis<T>(KV2) );
182 cbases.push_back(new gsBSplineBasis<T>(KV3) );
183 cbases.push_back(new gsBSplineBasis<T>(KV4) );
184 TBasis * tbasis = gsBSplineTraits<d,T>::Basis::New(cbases); //d==4
185
186 GISMO_ASSERT(tbasis->size()== tcoefs.rows(),
187 "Coefficient matrix for the NURBS does not have "
188 "the expected number of control points (rows)." );
189
190 this->m_basis = new Basis(tbasis, give(wgts));
191 this->m_coefs.swap(tcoefs);
192 }
193
194 GISMO_BASIS_ACCESSORS
195
196 public:
197
198// ***********************************************
199// Virtual member functions required by the base class
200// ***********************************************
201
202 GISMO_CLONE_FUNCTION(gsTensorNurbs)
203
204
205 std::ostream &print(std::ostream &os) const
206 { os << "Tensor-NURBS geometry "<< "R^"<< this->parDim() <<
207 " --> R^"<< this->geoDim()<< ", #control pnts= "<< this->coefsSize() <<": "
208 << this->coef(0) <<" ... "<< this->coef(this->coefsSize()-1);
209 os << "\nweights: "
210 << this->basis().weights().at(0) <<" ... "
211 << this->basis().weights().at(this->coefsSize()-1)
212 <<"\n" ;
213 return os; }
214
215// ***********************************************
216// Additional members for tensor NURBS
217// ***********************************************
218
220 const KnotVectorType & knots(const int i) const
221 { return this->basis().source().knots(i); }
222
223 KnotVectorType & knots(const int i)
224 { return this->basis().source().knots(i); }
225
227 void insertKnot( T knot, int dir, int i = 1)
228 {
229 GISMO_ASSERT( i>0, "multiplicity must be at least 1");
230 GISMO_ASSERT( dir >= 0 && static_cast<unsigned>(dir) < d,
231 "Invalid basis component "<< dir <<" requested for degree elevation" );
232
233 // Combine control points and weights to n+1 dimensional "control points"
234 gsMatrix<T> projectiveCoefs = basis().projectiveCoefs(m_coefs, weights());
235
236 // Dimension of physical space + 1 for the weights
237 const index_t n = projectiveCoefs.cols();
238
239 gsTensorBSplineBasis<d,T> & tbs = this->basis().source();
241 tbs.size_cwise(sz); // Size of basis per (parametric) direction
242
243 swapTensorDirection(0, dir, sz, projectiveCoefs );
244
245 const index_t nc = sz.template tail<static_cast<short_t>(d-1)>().prod();
246 projectiveCoefs.resize( sz[0], n * nc );
247
248 // Insert knot and update projective control points
249 gsBoehm(tbs.knots(dir), projectiveCoefs , knot, i, true );
250 sz[0] = projectiveCoefs.rows();
251
252 // New number of coefficients
253 const index_t ncoef = sz.prod();
254 projectiveCoefs.resize(ncoef, n );
255
256 swapTensorDirection(0, dir, sz, projectiveCoefs );
257
258 // Unpack projective control points and update the coefs and weights of the original NURBS
259 basis().setFromProjectiveCoefs(projectiveCoefs, m_coefs, weights() );
260 }
261
263 T & weight(int i) const { return this->basis().weight(i); }
264
266 const gsMatrix<T> & weights() const { return this->basis().weights(); }
267
269 gsMatrix<T> & weights() { return this->basis().weights(); }
270
272 short_t degree(unsigned i) const
273 { return this->basis().source().component(i).degree(); }
274
276 void reverse(unsigned k)
277 {
278 GISMO_ASSERT(d==2, "only 2D for now");
279
280 gsVector<int> str(d);
281 gsVector<int> sz (d);
282
283 gsTensorBSplineBasis<d,T> & tbsbasis = this->basis().source();
284
285 sz[0] = tbsbasis.component(k ).size();
286 sz[1] = tbsbasis.component(!k).size();
287 str[0] = tbsbasis.source().stride( k );
288 str[1] = tbsbasis.source().stride(!k );
289
290 gsMatrix<T> & w = tbsbasis.weights();
291
292 for ( int i=0; i< sz[0]; i++ )
293 for ( int j=0; j< sz[1]/2; j++ )
294 {
295 this->m_coefs.row(i*str[0] + j*str[1] ).swap(
296 this->m_coefs.row(i*str[0] + (sz[1]-j-1)*str[1] )
297 );
298
299 w.row(i*str[0] + j*str[1] ).swap(
300 w.row(i*str[0] + (sz[1]-j-1)*str[1] )
301 );
302 }
303 tbsbasis.component(k).reverse();
304 }
305
309 void slice(index_t dir_fixed, T par, BoundaryGeometryType & result) const
310 {
311 GISMO_ASSERT(d-1>=0,"d must be greater or equal than 1");
312 GISMO_ASSERT(dir_fixed>=0 && static_cast<unsigned>(dir_fixed)<d,"cannot fix a dir greater than dim or smaller than 0");
313 // construct the d-1 basis
314 boxSide side(dir_fixed,0);
315 //typename gsTensorNurbsBasis<static_cast<short_t>(d-1),T>::uPtr tbasis = this->basis().boundaryBasis(side);
316 typename BoundaryBasisType::uPtr tbasis = this->basis().boundaryBasis(side);
317
318 if(d==1)
319 {
320 gsMatrix<T> val(1,1),point;
321 val(0,0)=par;
322 this->eval_into(val,point);
323 //result = gsTensorNurbs<static_cast<short_t>(d-1), T>(*tbasis, point );
324 result = BoundaryGeometryType(*tbasis, point );
325 }
326 else
327 {
328 const int mult = this->basis().knots(dir_fixed).multiplicity(par);
329 const int degree = this->basis().degree(dir_fixed);
330
332 if( mult>=degree )
333 {
334 // no knot insertion needed, just extract the right coefficients
335 const gsKnotVector<T>& knots = this->basis().knots(dir_fixed);
336 const index_t index = (knots.iFind(par) - knots.begin()) - this->basis().degree(dir_fixed);
338 this->basis().size_cwise(sizes);
339 constructCoefsForSlice<d, T>(dir_fixed, index, this->coefs(), sizes, coefs);
340 }
341 else
342 {
343 // clone the basis and inserting up to degree knots at par
344 gsTensorNurbs<d,T>* clone = this->clone().release();
345
346 gsVector<index_t,d> intStrides;
347 this->basis().stride_cwise(intStrides);
349 clone->basis().knots(dir_fixed),clone->coefs(),par,dir_fixed,
350 intStrides.template cast<unsigned>(), degree-mult,true);
351
352 // extract right ceofficients
353 const gsKnotVector<T>& knots = clone->basis().knots(dir_fixed);
354 const index_t index = (knots.iFind(par) - knots.begin()) - clone->basis().degree(dir_fixed);
356 clone->basis().size_cwise(sizes);
357 constructCoefsForSlice<d, T>(dir_fixed, index, clone->coefs(), sizes, coefs);
358 delete clone;
359 }
360
361 // construct the object
362 //result = gsTensorBSpline<static_cast<short_t>(d-1),T>(*tbasis, give(coefs) );
363 //result = BoundaryGeometry(*tbasis, give(coefs) );
364 result = BoundaryGeometryType (*tbasis, coefs );
365 }
366 }
367
368 void swapDirections(const unsigned i, const unsigned j)
369 {
371 this->basis().size_cwise(sz);
372 swapTensorDirection(i, j, sz, m_coefs);
373 this->basis().swapDirections(i,j);
374 }
375
379 std::vector<gsGeometry<T>*> uniformSplit(index_t dir = -1) const
380 {
381 // We use the simple fact that a NURBS function in R^d is the central probjection
382 // of a spline function in R^{d+1} into R^d.
383 //
384 // Create a B-spline in R^{d+1} and split it
385 Basis& basis = static_cast<Basis&>(*m_basis); // Basis is here gsTensorNurbsBasis
386 std::vector<gsGeometry<T>*> result
387 = gsTensorBSpline<d,T>(basis.source(), basis.projectiveCoefs(m_coefs)).uniformSplit(dir);
388 // Turn the B-splines in R^{d+1} back into NURBS in R^d
389 for ( typename std::vector<gsGeometry<T>*>::iterator it = result.begin();
390 it != result.end(); ++it )
391 {
392 gsTensorBSpline<d,T>* spline = static_cast<gsTensorBSpline<d,T>*>(*it);
393 gsTensorNurbsBasis<d,T>* nurbsBasis = new gsTensorNurbsBasis<d,T>(spline->basis().clone().release());
395 nurbs->m_basis = nurbsBasis;
397 spline->coefs(),
398 nurbs->m_coefs,
399 nurbsBasis->weights()
400 );
401 delete *it;
402 *it = nurbs;
403 }
404 return result;
405 }
406
407
411 void splitAt(index_t dir,T xi, gsTensorNurbs<d,T>& left, gsTensorNurbs<d,T>& right) const
412 {
413 // We use the simple fact that a NURBS function in R^d is the central projection
414 // of a spline function in R^{d+1} into R^d.
415 //
416 // Create a B-spline in R^{d+1} and split it
417 Basis& basis = static_cast<Basis&>(*m_basis); // Basis is here gsTensorNurbsBasis
418 gsTensorBSpline<d,T> leftBS, rightBS;
419 gsTensorBSpline<d,T> tmp(basis.source(), basis.projectiveCoefs(m_coefs));
420
421 // Use gsTensorBSpline::splitAt() with the projective coefs.
422 tmp.splitAt(dir, xi, leftBS, rightBS);
423
424
425 // Turn the B-splines in R^{d+1} back into NURBS in R^d
426 // gsTensorBSpline<d,T>* spline = static_cast<gsTensorBSpline<d,T>*>(*it);
427
428 gsTensorNurbsBasis<d,T>* leftBasis = new gsTensorNurbsBasis<d,T>(leftBS.basis().clone().release());
429 gsTensorNurbs<d,T>* leftNurbs = new gsTensorNurbs<d,T>;
430 leftNurbs->m_basis = leftBasis;
431
433 leftBS.coefs(),
434 leftNurbs->m_coefs,
435 leftBasis->weights());
436
437 gsTensorNurbsBasis<d,T>* rightBasis = new gsTensorNurbsBasis<d,T>(rightBS.basis().clone().release());
438 gsTensorNurbs<d,T>* rightNurbs = new gsTensorNurbs<d,T>;
439 rightNurbs->m_basis = rightBasis;
440
442 rightBS.coefs(),
443 rightNurbs->m_coefs,
444 rightBasis->weights());
445
446
447 left = gsTensorNurbs<d,T>( *leftBasis, leftNurbs->coefs() );
448 right = gsTensorNurbs<d,T>( *rightBasis, rightNurbs->coefs());
449 }
450
451protected:
452 // todo: check function: check the coefficient number, degree, knot vector ...
453
454 using gsGeometry<T>::m_coefs;
455 using gsGeometry<T>::m_basis;
456
457}; // class gsTensorNurbs
458
459
460// ***********************************************
461// ***********************************************
462
463
464} // 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 const gsMatrix< T > & weights() const
Only for compatibility reasons, with gsRationalBasis. It returns an empty matrix.
Definition gsBasis.h:411
virtual const gsBasis & source() const
Definition gsBasis.h:710
uPtr clone()
Clone methode. Produceds a deep copy inside a uPtr.
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
void eval_into(const gsMatrix< T > &u, gsMatrix< T > &result) const
Evaluate the function at points u into result.
Definition gsGeometry.hpp:166
short_t geoDim() const
Dimension n of the absent physical space.
Definition gsGeometry.h:292
virtual const gsBasis< T > & basis() const =0
Returns a const reference to the basis of the geometry.
short_t parDim() const
Dimension d of the parameter domain (same as domainDim()).
Definition gsGeometry.hpp:190
gsBasis< T > * m_basis
Pointer to the basis of this geometry.
Definition gsGeometry.h:632
gsMatrix< T > m_coefs
Coefficient matrix of size coefsSize() x geoDim()
Definition gsGeometry.h:629
index_t coefsSize() const
Return the number of coefficients (control points)
Definition gsGeometry.h:371
Class for representing a knot vector.
Definition gsKnotVector.h:80
int degree() const
Returns the degree of the knot vector.
Definition gsKnotVector.hpp:700
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
static void setFromProjectiveCoefs(const gsMatrix< T > &pr_coefs, gsMatrix< T > &coefs, gsMatrix< T > &weights)
Definition gsRationalBasis.h:356
const gsMatrix< T > & weights() const
Returns the weights of the rational basis.
Definition gsRationalBasis.h:300
A tensor product B-spline basis.
Definition gsTensorBSplineBasis.h:37
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 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
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 tensor product Non-Uniform Rational B-spline (NURBS) basis.
Definition gsTensorNurbsBasis.h:38
memory::unique_ptr< gsTensorNurbsBasis > uPtr
Unique pointer for gsTensorNurbsBasis.
Definition gsTensorNurbsBasis.h:70
A tensor product Non-Uniform Rational B-spline function (NURBS) of parametric dimension d,...
Definition gsTensorNurbs.h:41
void insertKnot(T knot, int dir, int i=1)
Inserts knot knot at direction dir, i times.
Definition gsTensorNurbs.h:227
gsTensorNurbs(gsKnotVector< T > const &KV1, gsKnotVector< T > const &KV2, gsKnotVector< T > const &KV3, gsMatrix< T > tcoefs)
Definition gsTensorNurbs.h:145
gsTensorNurbs(gsKnotVector< T > const &KV1, gsKnotVector< T > const &KV2, gsKnotVector< T > const &KV3, gsMatrix< T > tcoefs, gsMatrix< T > wgts)
Definition gsTensorNurbs.h:121
memory::unique_ptr< gsTensorNurbs > uPtr
Unique pointer for gsTensorNurbs.
Definition gsTensorNurbs.h:69
gsTensorNurbs(gsKnotVector< T > const &KV1, gsKnotVector< T > const &KV2, gsMatrix< T > tcoefs, gsMatrix< T > wgts)
Construct 2D tensor NURBS by knot vectors, degrees, weights and coefficient matrix.
Definition gsTensorNurbs.h:100
void reverse(unsigned k)
Toggle orientation wrt coordinate k.
Definition gsTensorNurbs.h:276
gsBSplineTraits< static_cast< short_t >(d-1), T >::RatGeometry BoundaryGeometryType
Associated boundary geometry type.
Definition gsTensorNurbs.h:59
void splitAt(index_t dir, T xi, gsTensorNurbs< d, T > &left, gsTensorNurbs< d, T > &right) const
Definition gsTensorNurbs.h:411
const gsMatrix< T > & weights() const
Returns the NURBS weights.
Definition gsTensorNurbs.h:266
std::vector< gsGeometry< T > * > uniformSplit(index_t dir=-1) const
Definition gsTensorNurbs.h:379
const KnotVectorType & knots(const int i) const
Returns a reference to the knot vector i.
Definition gsTensorNurbs.h:220
gsTensorNurbs()
Default empty constructor.
Definition gsTensorNurbs.h:74
gsTensorNurbs(gsKnotVector< T > const &KV1, gsKnotVector< T > const &KV2, gsMatrix< T > tcoefs)
Definition gsTensorNurbs.h:81
T & weight(int i) const
Access to i-th weight.
Definition gsTensorNurbs.h:263
void slice(index_t dir_fixed, T par, BoundaryGeometryType &result) const
Definition gsTensorNurbs.h:309
gsBSplineTraits< static_cast< short_t >(d-1), T >::RatBasis BoundaryBasisType
Associated boundary basis type.
Definition gsTensorNurbs.h:63
gsBSplineBasis< T > Family_t
Family type.
Definition gsTensorNurbs.h:53
gsMatrix< T > & weights()
Returns the NURBS weights as non-const reference.
Definition gsTensorNurbs.h:269
std::ostream & print(std::ostream &os) const
Prints the object as a string.
Definition gsTensorNurbs.h:205
gsTensorNurbs(gsKnotVector< T > const &KV1, gsKnotVector< T > const &KV2, gsKnotVector< T > const &KV3, gsKnotVector< T > const &KV4, gsMatrix< T > tcoefs, gsMatrix< T > wgts)
Definition gsTensorNurbs.h:168
memory::shared_ptr< gsTensorNurbs > Ptr
Shared pointer for gsTensorNurbs.
Definition gsTensorNurbs.h:66
short_t degree(unsigned i) const
Returns the degree of the basis wrt direction i.
Definition gsTensorNurbs.h:272
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
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Provides declaration of Geometry abstract interface.
Provides declaration of TensorNurbsBasis abstract interface.
Utility functions related to tensor-structured objects.
The G+Smo namespace, containing all definitions for the library.
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
S give(S &x)
Definition gsMemory.h:266
Traits for BSplineBasis in more dimensions.
Definition gsBSplineBasis.h:32