G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsBSpline.h
Go to the documentation of this file.
1
14#pragma once
15
17#include <gsCore/gsGeometry.h>
18
20#include <gsNurbs/gsBoehm.h>
22
23#include <gsUtils/gsPointGrid.h>
24
25namespace gismo {
26namespace internal {
27
28template<class T>
29struct gsCurveIntersectionResult;
30
31} // namespace internal
32} // namespace gismo
33
34namespace gismo
35{
36
49template<class T>
50class gsBSpline : public gsGeoTraits<1,T>::GeometryBase
51{
52public:
53 typedef gsKnotVector<T> KnotVectorType;
54
55 typedef typename gsGeoTraits<1,T>::GeometryBase Base;
56
57 typedef gsBSplineBasis<T> Basis;
58
60 typedef memory::shared_ptr< gsBSpline > Ptr;
61
63 typedef memory::unique_ptr< gsBSpline > uPtr;
64
65public:
66
69
70 // enable swap
71 using gsGeometry<T>::swap;
72
74 gsBSpline( const Basis & basis, gsMatrix<T> coefs )
75 : Base( basis, give(coefs) )
76 {
77 if( this->basis().isPeriodic() )
78 this->basis().expandCoefs(m_coefs);
79 }
80
82 gsBSpline(KnotVectorType KV, gsMatrix<T> coefs, bool periodic = false )
83 {
84 this->m_basis = new Basis(give(KV));
85 m_coefs.swap(coefs);
86
87 if( periodic )
88 {
89 const index_t sz = this->basis().size();
90
91 this->basis().setPeriodic();
92
93 if ( m_coefs.rows() == sz )
94 {
95 this->basis().trimCoefs(m_coefs);
96 }
97 else if ( m_coefs.rows() == this->basis().size() )
98 {
99 this->basis().expandCoefs(m_coefs);
100 }
101 else
102 {
103 GISMO_ERROR("Wrong number of coefficients for periodic basis.");
104 }
105 }
106 else // non-periodic
107 {
108 if( this->m_coefs.rows() + KV.degree() + 1 != static_cast<int>( this->knots().size() ) )
109 gsWarn << "gsBSpline Warning: #Knots="<< this->knots().size()<< ", #coefs="<< this->m_coefs.rows() <<"\n";
110 }
111 }
112
113
124 gsBSpline(T u0, T u1, unsigned interior, int degree,
125 gsMatrix<T> coefs, unsigned mult_interior=1, bool periodic = false)
126 {
127 this->m_basis = new Basis(u0, u1, interior, degree, mult_interior, periodic );
128 if( periodic )
129 {
130 GISMO_ASSERT( this->basis().numCrossingFunctions() == 1,
131 "Knot vector with clamped knots should lead to m_periodic == 1.");
132
133 this->m_coefs = this->basis().perCoefs(coefs);
134 GISMO_ASSERT( this->m_coefs.rows() >= this->basis().size(),
135 "You should give at least as many coefficients as the size of the basis after converting to periodic.");
136 if( this->m_coefs.rows() > this->basis().size() )
137 gsWarn << "Some of the last coefficients are going to be lost during conversion to periodic basis.\n";
138 }
139 else // non-periodic
140 {
141 this->m_coefs.swap(coefs);
142 GISMO_ASSERT( this->m_coefs.rows() == this->basis().size(),
143 "Number of coefficients does not match the size of the basis.");
144 }
145 }
146
147 GISMO_CLONE_FUNCTION(gsBSpline)
148
149 GISMO_BASIS_ACCESSORS
150
151public:
152
154 std::ostream &print(std::ostream &os) const
155 {
156 os << "BSpline curve "<< "of degree "<< this->basis().degree()<< ", "<< this->basis().knots() <<".\n";
157 os << "with control points "<< this->m_coefs.row(0)<<" ... "<<this->m_coefs.bottomRows(1) << ".\n";
158 if( this->basis().isPeriodic() )
159 os << "Periodic with overlay " << this->basis().numCrossingFunctions() << ".\n";
160 return os;
161 }
162
164 T domainStart() const { return *this->basis().knots().domainBegin(); }
165
167 T domainEnd() const { return *this->basis().knots().domainEnd(); }
168
170 KnotVectorType & knots(const int i = 0)
171 {
172 GISMO_UNUSED(i);
173 GISMO_ASSERT( i==0, "Requested knots of invalid direction "<< i );
174 return this->basis().knots();
175 }
176
178 const KnotVectorType & knots(const int i = 0) const
179 {
180 GISMO_UNUSED(i);
181 GISMO_ASSERT( i==0, "Requested knots of invalid direction "<< i );
182 return this->basis().knots();
183 }
184
186 short_t degree(short_t i = 0) const
187 {
188 GISMO_UNUSED(i);
189 GISMO_ASSERT( i==0, "Requested knots of invalid direction "<< i );
190 return this->basis().degree();
191 }
192
193 // compatible curves: same degree, same first/last p+1 knots
194 void isCompatible( gsGeometry<T> * )
196
197 // compatible curves: same degree, same first/last p+1 knots
198 void makeCompatible( gsGeometry<T> * )
200
201
203 void merge( gsGeometry<T> * otherG );
204
211 gsBSpline<T> segmentFromTo(T u0, T u1, T tolerance=1e-15) const;
212
219 void splitAt(T u0, gsBSpline<T>& left, gsBSpline<T>& right, T tolerance=1e-15) const;
220
224 gsMultiPatch<T> toBezier(T tolerance=1e-15) const;
225
232 std::vector<internal::gsCurveIntersectionResult<T>> intersect(const gsBSpline<T>& other, T tolerance = 1e-5, T curvatureTolerance=1+1e-6) const;
233
237 T pseudoCurvature() const;
238
241 void insertKnot( T knot, index_t i = 1);
242private:
243 // Resolve hidden overload w.r.t. gsGeometry
244 virtual void insertKnot( T knot, index_t dir, index_t i = 1);
245public:
246
252 template <class It>
253 void insertKnots( It inBegin, It inEnd)
254 {
255 if( this->basis().isPeriodic() )
256 {
257 // We assume we got valid (i.e., non-NULL) iterators; I don't think we have a reasonable way to test it in GISMO_ASSERT.
258
259 GISMO_ASSERT( (*inBegin > *(this->knots().begin()))
260 && (*(inEnd-1) < *(this->knots().end()-1)),
261 "Please, ask me to insert knots inside the knot interval only." );
262
263 std::vector<T> newKnots(inBegin,inEnd);
264
265 // It can happen that user would ask us to insert knots outside the active range.
266 // Should it happen, we shift the values and then sort the knot vector to remain non-decreasing.
267
268 T activeLength = this->basis()._activeLength();
269 T blue1 = *(this->basis().knots().begin() + this->degree() );
270 T blue2 = *(this->basis().knots().end() - this->degree() );
271 typename std::vector<T>::iterator begin = newKnots.begin();
272 typename std::vector<T>::iterator end = newKnots.end();
273 for( typename std::vector<T>::iterator it = begin; it != end; ++it )
274 {
275 if( *it < blue1 )
276 *it += activeLength;
277 else if( *it > blue2 )
278 *it -= activeLength;
279 else if( (*it == blue1) || (*it == blue2) )
280 {
281 // I would like to erase it and go on but for that the iterator is not enough.
282 // ANGELOS, wouldn't it be better to put a GISMO_ASSERT here instead? Or throw an exception?
283 gsWarn << "Interrupting insertKnots(): Cannot insert value equal to the p+1st knot from the beginning or end into a periodic curve.\n";
284 return;
285 }
286 }
287 /* // This way it would be nicer but it does not cover all the dubious cases.
288 for( It it = begin; *it < blue1; ++it )
289 *it += activeLength;
290 for( It it = end-1; *it > blue2; --it )
291 *it -= activeLength;*/
292
293 std::sort( begin, end );
294
295 // We copy some of the control points to pretend for a while that the basis is not periodic.
296 //gsMatrix<T> trueCoefs = this->basis().perCoefs( this->coefs() );
297 gsBoehmRefine( this->basis().knots(), this->coefs(), this->degree(), begin, end );
298 //this->basis().enforceOuterKnotsPeriodic();
299 //this->coefs() = trueCoefs; // Isn't this memory-leaking?
300 // Periodic basis is restored using the so-called Student's Algorithm: forget as much as possible =).
301 //this->coefs().conservativeResize( this->basis().size(), this->coefs().cols() );
302 }
303 else // non-periodic
304 gsBoehmRefine( this->basis().knots(), this->coefs(), this->degree(), inBegin, inEnd);
305 }
306
307 // Look at gsGeometry class for a description
308 void degreeElevate(short_t const i = 1, short_t const dir = -1);
309
312 // Under Construction..( TO DO )
313 bool contains( gsMatrix<T> const & p, T const & tol = 1e-6 )
314 {
315 assert( p.cols()==1 );
317 std::vector<T> roots;
318 short_t dim = this->geoDim();
319 gsMatrix<T> ev, tmp(1,1);
320 int i(1);
321
322 slv.allRoots( *this, roots, 0, p(0,0), 1e-6, 100);
323 for ( typename std::vector<T>::const_iterator it=roots.begin();
324 it != roots.end(); ++it)
325 {
326 tmp(0,0)= *it;
327 this->eval_into(tmp,ev);
328 for (i=1; i!=dim; ++i )
329 if ( math::abs( ev(i,0) - p(i,0) ) > tol )
330 break;
331 if (i==dim)
332 return true;
333 }
334 return false;
335 }
336
338 gsMatrix<T> sample(int npoints = 50) const
339 {
340 gsMatrix<T> images;
341 gsMatrix<T> interval = this->parameterRange();
342 const gsMatrix<T> pts = gsPointGrid(interval, npoints );
343 this->eval_into( pts, images );
344 return images;
345 }
346
348 void setPeriodic(bool flag = true)
349 {
350 this->basis().setPeriodic(flag);
351 this->m_coefs = this->basis().perCoefs( this->m_coefs );
352 }
353
354 inline int numCoefs() const { return this->m_coefs.rows() - this->basis().numCrossingFunctions(); }
355
356 inline bool isPeriodic() const { return this->basis().isPeriodic(); }
357
358
360 bool isClosed(T tol = 1e-10) const
361 {
362 return ( this->basis().isPeriodic() ||
363 (m_coefs.row(0) - m_coefs.row(m_coefs.rows()-1)).squaredNorm()<tol );
364 }
365
368 bool isOn(gsMatrix<T> const &u, T tol = 1e-3) const;
369
372 bool isPatchCorner(gsMatrix<T> const &v, T tol = 1e-3) const;
373
377 void findCorner(const gsMatrix<T> & v,
378 gsVector<index_t,1> & curr,
379 T tol = 1e-3);
380
384 void setOriginCorner(gsMatrix<T> const &v);
385
389 void setFurthestCorner(gsMatrix<T> const &v);
390
391 void swapDirections(const unsigned i, const unsigned j);
392
393private:
394
395 // Avoid hidden overloads w.r.t. gsGeometry
396 using Base::insertKnot;
397
398protected:
399
400 using Base::m_coefs;
401
402 // TODO Check function
403 // check function: check the coefficient number, degree, knot vector ...
404}; // class gsBSpline
405
406
407#ifdef GISMO_WITH_PYBIND11
408
412 void pybind11_init_gsBSpline(pybind11::module &m);
413
414#endif // GISMO_WITH_PYBIND11
415
416
417/*
418// Product of spline functions
419template<class T>
420gsBSpline<T> operator*(const gsBSpline<T> & lhs, const gsBSpline<T> & rhs)
421{
422 // Note: quick-fix implementation. Better algorithms exist
423 gsKnotVector<T> kv = lhs.knots().knotUnion( lhs.knots() );
424 kv.degreeElevate( lhs.degree() + rhs.degree() - kv.degree() );
425
426 gsMatrix<T> pts;
427 kv.greville_into(pts);
428 const gsMatrix<T> ev = (lhs.eval(pts)).array() * (rhs.eval(pts)).array();
429
430 // fixme: avoid temporaries here
431 return *(static_cast<gsBSpline<T>*>(gsBSplineBasis<T>(kv).interpolateData(ev,pts)));
432}
433*/
434
435} // namespace gismo
436
437
438#ifndef GISMO_BUILD_LIB
439#include GISMO_HPP_HEADER(gsBSpline.hpp)
440#endif
A univariate B-spline basis.
Definition gsBSplineBasis.h:700
Definition gsBSplineSolver.h:114
A B-spline function of one argument, with arbitrary target dimension.
Definition gsBSpline.h:51
void merge(gsGeometry< T > *otherG)
Merge other B-spline into this one.
Definition gsBSpline.hpp:29
gsMatrix< T > sample(int npoints=50) const
Sample npoints uniformly distributed (in parameter domain) points on the curve.
Definition gsBSpline.h:338
bool isOn(gsMatrix< T > const &u, T tol=1e-3) const
Return true if point u is on the curve with tolerance tol.
Definition gsBSpline.hpp:265
bool isClosed(T tol=1e-10) const
Returns true if this curve is closed.
Definition gsBSpline.h:360
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 gsBSpline.hpp:347
bool contains(gsMatrix< T > const &p, T const &tol=1e-6)
Returns true iff the point p is contained (approximately) on the curve, with the given tolerance.
Definition gsBSpline.h:313
T pseudoCurvature() const
Definition gsBSpline.hpp:189
memory::unique_ptr< gsBSpline > uPtr
Unique pointer for gsBSpline.
Definition gsBSpline.h:63
gsBSpline(const Basis &basis, gsMatrix< T > coefs)
Construct B-Spline by basis and coefficient matrix.
Definition gsBSpline.h:74
void setOriginCorner(gsMatrix< T > const &v)
Modifies the parameterization such that the point v is the starting point of the curve....
Definition gsBSpline.hpp:315
memory::shared_ptr< gsBSpline > Ptr
Shared pointer for gsBSpline.
Definition gsBSpline.h:60
void insertKnot(T knot, index_t i=1)
Definition gsBSpline.hpp:249
gsBSpline(KnotVectorType KV, gsMatrix< T > coefs, bool periodic=false)
Construct B-Spline by a knot vector and coefficient matrix.
Definition gsBSpline.h:82
gsMultiPatch< T > toBezier(T tolerance=1e-15) const
Definition gsBSpline.hpp:138
void splitAt(T u0, gsBSpline< T > &left, gsBSpline< T > &right, T tolerance=1e-15) const
Definition gsBSpline.hpp:255
gsBSpline()
Default empty constructor.
Definition gsBSpline.h:68
KnotVectorType & knots(const int i=0)
Returns a reference to the knot vector.
Definition gsBSpline.h:170
void insertKnots(It inBegin, It inEnd)
Definition gsBSpline.h:253
void setFurthestCorner(gsMatrix< T > const &v)
Modifies the parameterization such that the point v is the ending point of the curve....
Definition gsBSpline.hpp:326
void findCorner(const gsMatrix< T > &v, gsVector< index_t, 1 > &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 gsBSpline.hpp:298
T domainEnd() const
Returns the end value of the domain of the basis.
Definition gsBSpline.h:167
const KnotVectorType & knots(const int i=0) const
Returns a (const )reference to the knot vector.
Definition gsBSpline.h:178
bool isPatchCorner(gsMatrix< T > const &v, T tol=1e-3) const
Return true if point u is an endpoint (corner) of the curve with tolerance tol.
Definition gsBSpline.hpp:291
void setPeriodic(bool flag=true)
Tries to convert the curve into periodic.
Definition gsBSpline.h:348
gsBSpline< T > segmentFromTo(T u0, T u1, T tolerance=1e-15) const
Definition gsBSpline.hpp:87
short_t degree(short_t i=0) const
Returns the degree of the B-spline.
Definition gsBSpline.h:186
gsMatrix< T > m_coefs
Coefficient matrix of size coefsSize() x geoDim()
Definition gsGeometry.h:629
std::ostream & print(std::ostream &os) const
Prints the object as a string.
Definition gsBSpline.h:154
std::vector< internal::gsCurveIntersectionResult< T > > intersect(const gsBSpline< T > &other, T tolerance=1e-5, T curvatureTolerance=1+1e-6) const
Definition gsBSpline.hpp:156
T domainStart() const
Returns the starting value of the domain of the basis.
Definition gsBSpline.h:164
Abstract base class representing a geometry map.
Definition gsGeometry.h:93
gsMatrix< T > & coefs()
Definition gsGeometry.h:340
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.
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
virtual void insertKnot(T knot, index_t dir, index_t i=1)
Inserts knot knot at direction dir, i times.
Definition gsGeometry.hpp:444
gsMatrix< T > parameterRange() const
Returns the range of parameters as a matrix with two columns, [lower upper].
Definition gsGeometry.hpp:198
Class for representing a knot vector.
Definition gsKnotVector.h:80
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition gsMatrix.h:41
A vector with arbitrary coefficient type and fixed or dynamic size.
Definition gsVector.h:37
gsBSpline(T u0, T u1, unsigned interior, int degree, gsMatrix< T > coefs, unsigned mult_interior=1, bool periodic=false)
Construct a B-spline from an interval and knot vector specification.
Definition gsBSpline.h:124
gsMatrix< T > gsPointGrid(gsVector< T > const &a, gsVector< T > const &b, gsVector< unsigned > const &np)
Construct a Cartesian grid of uniform points in a hypercube, using np[i] points in direction i.
Definition gsPointGrid.hpp:82
Provides declaration of BSplineBasis class.
Provides classes and functions to solve equations involving B-splines.
Boehm's algorithm for knot insertion.
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_NO_IMPLEMENTATION
Definition gsDebug.h:129
#define GISMO_ERROR(message)
Definition gsDebug.h:118
#define gsWarn
Definition gsDebug.h:50
#define GISMO_UNUSED(x)
Definition gsDebug.h:112
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Provides declaration of Geometry abstract interface.
This is the main header file that collects wrappers of Eigen for linear algebra.
Provides functions to generate structured point data.
The G+Smo namespace, containing all definitions for the library.
S give(S &x)
Definition gsMemory.h:266
void gsBoehmRefine(KnotVectorType &knots, Mat &coefs, int p, ValIt valBegin, ValIt valEnd, bool update_knots=true)
Definition gsBoehm.hpp:163