28 template<
class T,
class KnotVectorType,
class Mat>
30 KnotVectorType & knots,
38 GISMO_ASSERT( r >= 1,
"Must insert at least one knot." );
43 "Incompatible coefficients("<<coefs.rows()
44 <<
")/knots("<<knots.size()<<
")/degree("<<knots.degree()<<
")" ) ;
46 const int p = knots.degree();
47 typename KnotVectorType::uiterator kit = knots.uFind(val);
48 const int k = kit.lastAppearance();
50 const int s = (*kit == val || *(++kit)==val ? kit.multiplicity() : 0 );
57 GISMO_ASSERT( s + r < p + 2 ,
"Multiplicity can be at most deg+1 ("<<p+1<<
")" );
58 int np= coefs.rows()-1;
60 Mat tmp = coefs.middleRows(k-p, p+1);
62 coefs.conservativeResize( coefs.rows()+r, coefs.cols() );
65 for(
index_t i = np; i>=k-s; --i )
66 coefs.row(i+r) = coefs.row(i);
75 for(
index_t i = 0; i<=p-j-s; ++i )
77 a = (val - knots[L+i]) / (knots[i+k+1] - knots[L+i]);
78 tmp.row(i) = a * tmp.row(i+1) + (1.0-a) * tmp.row(i);
80 coefs.row(L)= tmp.row(0);
81 coefs.row(k+r-j-s)= tmp.row(math::max(p-j-s,(
index_t)0));
83 for(
index_t i = L+1; i<k-s; ++i )
84 coefs.row(i) = tmp.row(i-L);
94 template<
class T,
class KnotVectorType,
class Mat>
96 KnotVectorType & knots,
104 "Incompatible coefficients/knots" ) ;
106 int k = knots.iFind(val)-knots.begin();
107 int p = knots.degree();
109 coefs.duplicateRow( k );
118 for(
index_t i = k; i>=k-p+1; --i )
120 a = (val - knots[i]) / (knots[i+p] - knots[i]);
121 coefs.row(i) = (T(1)-a) * coefs.row(i-1) + a * coefs.row(i);
131 template<
class T,
class iter,
class Mat>
138 "Incompatible coefficients/knots" ) ;
143 coefs.conservativeResize( p+2, coefs.cols() );
148 coefs.row(p+1) = coefs.row(p);
152 for(
index_t i = p ; i>=1; --i )
154 a = (val - *knot) / ( *(knot+p) - *knot );
155 coefs.row(i) = (T(1)-a) * coefs.row(i-1) + a * coefs.row(i);
162 template<
class KnotVectorType,
class Mat,
class ValIt>
166 ValIt valBegin, ValIt valEnd,
169 if ( valBegin == valEnd )
return;
171 typedef typename std::iterator_traits<ValIt>::value_type T;
173 GISMO_ASSERT( (*valBegin >= knots[p]),
"Value is before first knot: "
174 << *valBegin <<
" < " <<knots[p] );
177 const int np= coefs.rows();
179 coefs.conservativeResize(np+nk, coefs.cols());
181 const int a = knots.iFind( *valBegin ) - knots.begin();
182 const int b = (knots.iFind( *(valEnd-1) ) - knots.begin()) + 1;
187 std::vector<T> nknots(knots.size()+nk);
190 for(
index_t j = np ; j > b-1; j--)
191 coefs.row( j+nk-1) = coefs.row(j-1);
194 for(
int j = 0; j <= a; j++)
195 nknots[j] = knots[j];
197 for(
size_t j = b+p; j < knots.size(); j++)
198 nknots[j + nk] = knots[j];
201 int k = b + p + nk-1;
203 for (
int j = nk-1; j>=0; j--)
205 const T newKnot = *(--valEnd);
207 while( (newKnot <= knots[i]) && (i>a) )
209 coefs.row(k-p-1) = coefs.row(i-p-1);
211 nknots[k] = knots[i];
216 coefs.row(k-p-1) = coefs.row(k-p);
219 for(
int l = 1 ; l <=p; l++)
221 const int ind = k-p+l;
223 T alfa = nknots[k+l] - newKnot;
226 coefs.row(ind-1) = coefs.row(ind);
229 alfa /= nknots[k+l]-knots[i-p+l];
230 coefs.row(ind-1) = alfa * coefs.row(ind-1) +
231 (1.0-alfa)*coefs.row(ind);
239 knots = KnotVectorType(p, nknots.begin(), nknots.end());
244 template<
typename T,
typename KnotVectorType,
typename Mat>
246 KnotVectorType& knots,
254 GISMO_ASSERT(1 <= r,
"Can not make insertion r < 1 times");
256 "We can not insert a knot in a given direction");
258 "We can not insert a knot outside of the knot vector interval");
261 int k = knots.iFind(val) - knots.begin();
262 int s = knots.multiplicity(val);
263 int p = knots.degree();
267 "Multiplicity of a knot must be lower (or equal) "
268 "than a degree. Otherwise, we get non-continuous function.");
271 int num_of_points = knots.size() - knots.degree() - 1;
272 unsigned points_to_add = (coefs.rows() / num_of_points) * r;
273 Mat new_coef = Mat(coefs.rows() + points_to_add, coefs.cols());
276 std::vector< std::vector<T> > alpha(r, std::vector<T> (p - s));
277 computeAlpha<T, KnotVectorType>(alpha, knots, val, r, k, p, s);
280 Mat tmp(p + 1, coefs.cols());
309 "We do not have an index for the new matrix.");
312 new_ind =
getIndex(new_str, new_position);
315 for (
int i = 0; i < k - p + 1; ++i)
317 new_coef.row(new_ind + i * new_step) = coefs.row(ind + i * step);
321 int tmp_ind = ind + step * (k - p);
322 for (
int i = 0; i < p + 1; ++i)
324 tmp.row(i) = coefs.row(tmp_ind + step * i);
329 for (
int j = 1; j <= r; ++j)
332 for (
int i = 0; i <= p - j - s; ++i)
334 T a = alpha[j - 1][i];
335 tmp.row(i) = a * tmp.row(i + 1) + (1.0 - a) * tmp.row(i);
338 new_coef.row(new_ind + new_step * L) = tmp.row(0);
339 new_coef.row(new_ind + new_step * (k + r - j - s)) =
344 for (
int i = L + 1; i < k - s; ++i)
346 new_coef.row(new_ind + step * i) = tmp.row(i - L);
350 for (
int i = k - s; i < num_of_points; ++i)
352 new_coef.row(new_ind + (i + r) * step) = coefs.row(ind + i * step);
355 flag = nextCubePoint<gsVector<int> >(new_position, first_point,
361 coefs =
give(new_coef);
365 knots.insert(val, r);
371 template <
typename KnotVectorType,
typename Mat,
typename ValIt>
373 KnotVectorType& knots,
382 typedef typename std::iterator_traits<ValIt>::value_type T;
384 const int npts = coefs.rows();
386 const int nk = knots.size();
387 const int p = knots.degree();
388 const int d = str.size();
390 GISMO_ASSERT(knots[p] <= *valBegin && *(valEnd - 1) <= knots[nk - p - 1],
391 "Can not insert knots, they are out of the knot range");
393 "We can not insert a knot in a given direction");
395 const int a = knots.iFind(*valBegin) - knots.begin();
396 const int b = (knots.iFind(*(valEnd - 1)) - knots.begin()) + 1;
399 int npts_in_dir = nk - p - 1;
400 int pts_to_add = (npts / npts_in_dir) * nik;
401 Mat new_coefs = Mat(npts + pts_to_add, coefs.cols());
404 std::vector<T> nknots(nk + nik);
411 for (
int i = 0; i < d; ++i)
420 getLastIndex(new_str, npts + pts_to_add, new_last_point);
431 std::vector< std::vector<T> > alpha(nik, std::vector<T> (p));
432 computeTensorAlpha<T, KnotVectorType, ValIt, std::vector<T> >
433 (alpha, nknots, knots, valBegin, valEnd);
437 ValIt valEndCopy = valEnd;
441 "We do not have an index for the new matrix.");
444 new_ind =
getIndex(new_str, new_position);
447 for (
int j = 0; j <= a - p; ++j)
448 new_coefs.row(new_ind + j * new_step) = coefs.row(ind + j * step);
449 for (
int j = npts_in_dir; b - 1 < j; --j)
450 new_coefs.row(new_ind + (j + nik - 1) * new_step) =
451 coefs.row(ind + (j - 1) * step);
455 int k = b + p + nik - 1;
457 for (
int j = nik - 1; 0 <= j; j--)
459 const T newKnot = *(--valEndCopy);
460 while ((newKnot <= knots[i]) && (a < i))
462 new_coefs.row(new_ind + (k - p - 1) * new_step) =
463 coefs.row(ind + (i - p - 1) * step);
468 new_coefs.row(new_ind + (k - p - 1) * new_step) =
469 new_coefs.row(new_ind + (k - p) * new_step);
471 for (
int ell = 1; ell <= p; ell++)
473 const T alfa = alpha[j][ell - 1];
474 const int index = k - p + ell;
477 new_coefs.row(new_ind + (index - 1) * new_step) =
478 new_coefs.row(new_ind + index * new_step);
480 new_coefs.row(new_ind + (index - 1) * new_step) =
481 alfa * new_coefs.row(new_ind + (index - 1) * new_step) +
482 (1.0 - alfa) * new_coefs.row(new_ind + index * new_step);
487 flag = nextCubePoint<gsVector<int> >(new_position, first_point,
493 coefs =
give(new_coefs);
496 knots = KnotVectorType(p, nknots.begin(), nknots.end());
500 template <
short_t d,
typename KnotVectorType,
typename Mat,
typename ValIt>
502 const unsigned index,
510 const bool update_knots)
513 if (valBegin==valEnd)
516 typedef typename std::iterator_traits<ValIt>::value_type T;
519 const index_t p = knots.degree();
521 const index_t nopts = knots.size() - p - 1;
525 const index_t a = knots.iFind(*valBegin) - knots.begin();
526 const index_t b = (knots.iFind(*(valEnd - 1)) - knots.begin()) + 1;
537 bspline::getLastIndexLocal<d>(nmb_of_coefs, last_point);
542 bspline::buildCoeffsStrides<d>(act_size_of_coefs, act_str);
551 std::vector< std::vector<T> > alpha(nik, std::vector<T> (p));
552 computeTensorAlpha<T, KnotVectorType, ValIt, gsSparseVector<T> >
553 (alpha, nknots, knots, valBegin, valEnd,
true);
555 unsigned iterations = 0;
561 if (number_of_iterations <= iterations)
565 ValIt valEndCopy = valEnd;
567 index_t ind = bspline::getIndex<d>(act_str, position);
569 for (
index_t j = b - 1; j < nopts; j++)
571 index_t indx1 = j + nik - index;
575 indx1 < act_size_of_coefs[direction])
578 coefs.row(ind + indx1 * step) = zero.row(0);
580 coefs.row(ind + indx1 * step) =
581 coefs.row(ind + indx2 * step);
587 int k = b + p + nik - 1;
589 for (
int j = nik - 1; 0 <= j; j--)
591 const T newKnot = *(--valEndCopy);
593 while ((newKnot <= knots[i]) && (a < i))
595 index_t indx1 = k - p - 1 - index;
596 index_t indx2 = i - p - 1 - index;
598 if (indx1 < 0 || act_size_of_coefs[direction] <= indx1)
607 coefs.row(ind + indx1 * step) = zero.row(0);
611 coefs.row(ind + indx1 * step) =
612 coefs.row(ind + indx2 * step);
618 index_t indx1 = k - p - 1 - index;
620 if (0 <= indx1 && (indx1 + 1) < act_size_of_coefs[direction])
621 coefs.row(ind + indx1 * step) =
622 coefs.row(ind + (indx1 + 1) * step);
624 if (indx1 == act_size_of_coefs[direction] - 1)
625 coefs.row(ind + indx1 * step) = zero.row(0);
627 for (
int ell = 1; ell <= p; ell++)
629 const T alfa = alpha[j][ell - 1];
630 const index_t mindex = k - p + ell - index;
635 if (act_size_of_coefs[direction] < mindex)
640 if (mindex == act_size_of_coefs[direction])
641 coefs.row(ind + (mindex - 1) * step) = zero.row(0);
643 coefs.row(ind + (mindex - 1) * step) =
644 coefs.row(ind + mindex * step);
648 if (mindex == act_size_of_coefs[direction])
649 coefs.row(ind + (mindex - 1) * step) =
650 alfa * coefs.row(ind + (mindex - 1) * step);
652 coefs.row(ind + (mindex - 1) * step) =
653 alfa * coefs.row(ind + (mindex - 1) * step) +
654 (1.0 - alfa) * coefs.row(ind + mindex * step);
666 for (ValIt knot_iter = valBegin; knot_iter != valEnd; ++knot_iter)
667 knots.insert(*knot_iter, 1);
756 template <
short_t d,
typename T,
typename KnotVectorType,
typename Mat>
758 const KnotVectorType& knots,
766 int k = knots.iFind(val) - knots.begin();
767 int s = knots.multiplicity(val);
768 int p = knots.degree();
774 const unsigned r = p - s;
776 std::vector<std::vector<T> > alpha(r, std::vector<T> (p - s));
777 computeAlpha<T, KnotVectorType>(alpha, knots, val, r, k, p, s);
780 bspline::buildCoeffsStrides<d>(size_of_coefs, coefs_str);
782 start(direction) = 0;
790 const unsigned flat_ind = bspline::getIndex<d>(coefs_str, position);
791 for (
unsigned j = 1; j <= r; j++)
793 for (
unsigned i = 0; i <= p - j - s; i++)
795 T alfa = alpha[j - 1][i];
796 coefs.row(flat_ind + i * step) =
797 alfa * coefs.row(flat_ind + (i + 1) * step) +
798 (1.0 - alfa) * coefs.row(flat_ind + i * step);
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
T distance(gsMatrix< T > const &A, gsMatrix< T > const &B, index_t i=0, index_t j=0, bool cols=false)
compute a distance between the point number in the set and the point number <j> in the set ; by def...
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
void computeTensorAlpha(std::vector< std::vector< T > > &alpha, newKnotsType &nknots, const KnotVectorType &knots, ValIt valBegin, ValIt valEnd, bool sparse=false)
Definition: gsBoehm.h:326
void gsBoehmRefine(KnotVectorType &knots, Mat &coefs, int p, ValIt valBegin, ValIt valEnd, bool update_knots=true)
Definition: gsBoehm.hpp:163
void gsTensorBoehmRefineLocal(KnotVectorType &knots, const unsigned index, Mat &coefs, gsVector< index_t, d > &nmb_of_coefs, const gsVector< index_t, d > &act_size_of_coefs, const gsVector< index_t, d > &size_of_coefs, const unsigned direction, ValIt valBegin, ValIt valEnd, const bool update_knots)
Local refinement algorithm.
Definition: gsBoehm.hpp:501
void correctNewStride(gsVector< unsigned > &new_str, const gsVector< unsigned > &str, const int direction, const int r)
Definition: gsBoehm.h:389
S give(S &x)
Definition: gsMemory.h:266
#define index_t
Definition: gsConfig.h:32
void gsTensorBoehmRefine(KnotVectorType &knots, Mat &coefs, int direction, gsVector< unsigned > str, ValIt valBegin, ValIt valEnd, bool update_knots=true)
Definition: gsBoehm.hpp:372
void gsTensorInsertKnotDegreeTimes(const KnotVectorType &knots, Mat &coefs, const gsVector< index_t, d > &size_of_coefs, T val, const unsigned direction, gsVector< index_t, d > &start, gsVector< index_t, d > &end)
Inserts knot val such that multiplicity of a val in knot vector is equal degree.
Definition: gsBoehm.hpp:757
Provides combinatorial unitilies.
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
void gsBoehmSingle(KnotVectorType &knots, Mat &coefs, T val, bool update_knots=true)
Performs knot insertion once on "knots" and coefficients "coefs".
Definition: gsBoehm.hpp:95
void getLastIndex(const gsVector< unsigned > &stride, const unsigned number_of_points, gsVector< int > &last_point)
Definition: gsBoehm.h:294
GISMO_DEPRECATED index_t direction(index_t s)
Returns the parametric direction that corresponds to side s.
Definition: gsBoundary.h:1048
unsigned numberOfIterations(const gsVector< index_t > &nmb_of_coefs, const unsigned direction)
Definition: gsBoehm.h:447
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
EIGEN_STRONG_INLINE abs_expr< E > abs(const E &u)
Absolute value.
Definition: gsExpressions.h:4486
void gsTensorBoehm(KnotVectorType &knots, Mat &coefs, T val, int direction, gsVector< unsigned > str, int r=1, bool update_knots=true)
Definition: gsBoehm.hpp:245
Sparse vector class, based on gsEigen::SparseVector.
Definition: gsSparseVector.h:34
void computeAlpha(std::vector< std::vector< T > > &alpha, const KnotVectorType &knots, T value, int r, int k, int p, int s)
Definition: gsBoehm.h:261
int getIndex(const gsVector< unsigned > &stride, const gsVector< int > &position)
Definition: gsBoehm.h:218