G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsBoehm.hpp
Go to the documentation of this file.
1 
14 #pragma once
15 
17 
18 namespace gismo
19 {
20 
26 
27 
28 template<class T, class KnotVectorType, class Mat>
29 void gsBoehm(
30  KnotVectorType & knots,
31  Mat & coefs,
32  T val,
33  int r,
34  bool update_knots
35  )
36 {
37 
38  GISMO_ASSERT( r >= 1, "Must insert at least one knot." );
39  if (r==1)
40  return gsBoehmSingle(knots, coefs, val, update_knots);
41 
42  GISMO_ASSERT( coefs.rows() == (index_t)(knots.size() - knots.degree()-1),
43  "Incompatible coefficients("<<coefs.rows()
44  <<")/knots("<<knots.size()<<")/degree("<<knots.degree()<<")" ) ;
45 
46  const int p = knots.degree();
47  typename KnotVectorType::uiterator kit = knots.uFind(val);
48  const int k = kit.lastAppearance();
49  // current multiplicity of val
50  const int s = (*kit == val || *(++kit)==val ? kit.multiplicity() : 0 );
51  /*
52  typename KnotVectorType::uiterator kit = knots.uFind(val);
53  int k = knots.iFind(val) - knots.begin();
54  int s = knots.multiplicity(val); // current multiplicity of val
55  */
56 
57  GISMO_ASSERT( s + r < p + 2 , "Multiplicity can be at most deg+1 ("<<p+1<<")" );
58  int np= coefs.rows()-1;
59 
60  Mat tmp = coefs.middleRows(k-p, p+1);
61  // resize coefficient matrix
62  coefs.conservativeResize( coefs.rows()+r, coefs.cols() );
63 
64  // shift control points that are not affected
65  for( index_t i = np; i>=k-s; --i )
66  coefs.row(i+r) = coefs.row(i);
67 
68  // Compute new control points
69  T a;
70  int L = 0;
71  for( index_t j = 1; j<=r; ++j )
72  {
73  L = k - p + j;
74 
75  for( index_t i = 0; i<=p-j-s; ++i )
76  {
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);
79  }
80  coefs.row(L)= tmp.row(0);
81  coefs.row(k+r-j-s)= tmp.row(math::max(p-j-s,(index_t)0));
82  }
83  for( index_t i = L+1; i<k-s; ++i )
84  coefs.row(i) = tmp.row(i-L);
85  //coefs.middleRows(L+1, k-s-L-1) = tmp.
86 
87  // Update knot vector
88  if ( update_knots )
89  knots.insert(val,r);
90 }
91 
92 
93 
94 template<class T, class KnotVectorType, class Mat>
96  KnotVectorType & knots,
97  Mat & coefs,
98  T val,
99  bool update_knots
100  )
101 {
102 
103  GISMO_ASSERT( coefs.rows() == (index_t)(knots.size() - knots.degree()-1),
104  "Incompatible coefficients/knots" ) ;
105 
106  int k = knots.iFind(val)-knots.begin();
107  int p = knots.degree();
108 
109  coefs.duplicateRow( k );
110  // // resize coefficient matrix
111  //coefs.conservativeResize(coefs.rows() + 1, coefs.cols());
112  //
113  //for (index_t i = coefs.rows() - 1; i >= k+1; --i)
114  // coefs.row(i) = coefs.row(i-1);
115 
116  // Compute new control points
117  T a;
118  for( index_t i = k; i>=k-p+1; --i )
119  {
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);
122  }
123 
124  // Update knot vector
125  if ( update_knots )
126  knots.insert(val);
127 }
128 
129 
130 
131 template<class T, class iter, class Mat>
132 void gsBoehmSingle( iter knot, // Knot iterator
133  Mat & coefs, // Coefficients (p+1)
134  int p, // degree
135  T val) // knot value to insert
136 {
137  GISMO_ASSERT( coefs.rows() == p+1,
138  "Incompatible coefficients/knots" ) ;
139 
140  knot++;
141 
142  // resize coefficient matrix by adding one coefficient
143  coefs.conservativeResize( p+2, coefs.cols() );
144 
145  // Shift coefficients by one place
146  // for (index_t i = p+1; i >= 1; --i)
147  // coefs.row(i) = coefs.row(i-1);
148  coefs.row(p+1) = coefs.row(p);
149 
150  // Compute new control points
151  T a;
152  for( index_t i = p ; i>=1; --i )
153  {
154  a = (val - *knot) / ( *(knot+p) - *knot );
155  coefs.row(i) = (T(1)-a) * coefs.row(i-1) + a * coefs.row(i);
156  knot++;
157  }
158 }
159 
160 
161 
162 template<class KnotVectorType, class Mat, class ValIt>
163 void gsBoehmRefine( KnotVectorType & knots,
164  Mat & coefs, //all Coefficients
165  int p, // degree --remove
166  ValIt valBegin, ValIt valEnd, // knot values to insert
167  bool update_knots)
168 {
169  if ( valBegin == valEnd ) return;
170 
171  typedef typename std::iterator_traits<ValIt>::value_type T;
172 
173  GISMO_ASSERT( (*valBegin >= knots[p]), "Value is before first knot: "
174  << *valBegin <<" < " <<knots[p] );
175  // && (val[val.size()-1]<=knots[knots.size()-p-1]));
176  //assert( knots[knots.size()-p-1]<=val[val.size()-1] );
177  const int np= coefs.rows();
178  const int nk= std::distance( valBegin, valEnd );
179  coefs.conservativeResize(np+nk, coefs.cols());
180 
181  const int a = knots.iFind( *valBegin ) - knots.begin();
182  const int b = (knots.iFind( *(valEnd-1) ) - knots.begin()) + 1;
183  //const int a = knots.uFind(*valBegin).lastAppearance();
184  //const int b = knots.uFind(*(valEnd-1)).lastAppearance() + 1;
185 
186  //gsKnotVector<T> nknots(p, knots.size()+nk);
187  std::vector<T> nknots(knots.size()+nk);
188 
189  // shift control points that are not affected
190  for(index_t j = np ; j > b-1; j--)
191  coefs.row( j+nk-1) = coefs.row(j-1);
192 
193  //std::copy( knots.begin(), knots.begin()+a+1,nknots.begin());
194  for(int j = 0; j <= a; j++)
195  nknots[j] = knots[j];
196  //std::copy( knots.begin()+b+p, knots.bend(),nknots.begin()+nk+b+p);
197  for(size_t j = b+p; j < knots.size(); j++)
198  nknots[j + nk] = knots[j];
199 
200  int i = b + p - 1;
201  int k = b + p + nk-1;
202 
203  for (int j = nk-1; j>=0; j--)
204  {
205  const T newKnot = *(--valEnd);
206 
207  while( (newKnot <= knots[i]) && (i>a) )
208  {
209  coefs.row(k-p-1) = coefs.row(i-p-1);
210 
211  nknots[k] = knots[i];
212  k-- ;
213  i-- ;
214  }
215 
216  coefs.row(k-p-1) = coefs.row(k-p);
217 
218 
219  for(int l = 1 ; l <=p; l++)
220  {
221  const int ind = k-p+l;
222 
223  T alfa = nknots[k+l] - newKnot;
224 
225  if( math::abs(alfa) == T(0.0) )
226  coefs.row(ind-1) = coefs.row(ind);
227  else
228  {
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);
232  }
233  }
234  nknots[k] = newKnot;
235  k--;
236  }
237 
238  if ( update_knots )
239  knots = KnotVectorType(p, nknots.begin(), nknots.end());
240  //knots.insert(valBegin, valEnd); // bug ?
241 }
242 
243 
244 template<typename T, typename KnotVectorType, typename Mat>
246  KnotVectorType& knots,
247  Mat& coefs,
248  T val,
249  const int direction,
250  gsVector<unsigned> str,
251  int r,
252  bool update_knots)
253 {
254  GISMO_ASSERT(1 <= r, "Can not make insertion r < 1 times");
255  GISMO_ASSERT(direction < str.size(),
256  "We can not insert a knot in a given direction");
257  GISMO_ASSERT(knots.first() < val && val < knots.last(),
258  "We can not insert a knot outside of the knot vector interval");
259 
260  int d = str.size(); // dimension
261  int k = knots.iFind(val) - knots.begin();
262  int s = knots.multiplicity(val);
263  int p = knots.degree();
264 
265 
266  GISMO_ASSERT(s + r <= p,
267  "Multiplicity of a knot must be lower (or equal) "
268  "than a degree. Otherwise, we get non-continuous function.");
269 
270  // we will compute new coefficients and put them new_coef matrix
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());
274 
275  // we precompute alpha (variable we use in knot insertion algorithm)
276  std::vector< std::vector<T> > alpha(r, std::vector<T> (p - s));
277  computeAlpha<T, KnotVectorType>(alpha, knots, val, r, k, p, s);
278 
279  // temporary matrix, for computation
280  Mat tmp(p + 1, coefs.cols());
281 
282  // compute stride for new coefficients
283  gsVector<unsigned> new_str(str);
284  correctNewStride(new_str, str, direction, r);
285 
286  // this two vectors will hold indices of current points
287  gsVector<int> position(d);
288  position.fill(0);
289  gsVector<int> new_position(position);
290 
291  // necessary for computation of the indices
292  gsVector<int> first_point(position);
293  gsVector<int> last_point(d);
294  gsVector<int> new_last_point(d);
295  getLastIndex(str, coefs.rows(), last_point);
296  getLastIndex(new_str, new_coef.rows(), new_last_point);
297  last_point[direction] = 0;
298  new_last_point[direction] = 0;
299 
300  int ind, new_ind; // actual indices (row of a coefs, new_coef)
301  unsigned step = str[direction];
302  unsigned new_step = new_str[direction];
303  bool flag = true; // safety flag
304 
305  do
306  {
307  if (!flag)
308  GISMO_ERROR("This should not happened!"
309  "We do not have an index for the new matrix.");
310 
311  ind = getIndex(str, position);
312  new_ind = getIndex(new_str, new_position);
313 
314  // copy untouched points from the begining
315  for (int i = 0; i < k - p + 1; ++i)
316  {
317  new_coef.row(new_ind + i * new_step) = coefs.row(ind + i * step);
318  }
319 
320  // make a temporary array of points
321  int tmp_ind = ind + step * (k - p);
322  for (int i = 0; i < p + 1; ++i)
323  {
324  tmp.row(i) = coefs.row(tmp_ind + step * i);
325  }
326 
327  // compute new control points
328  int L = 0;
329  for (int j = 1; j <= r; ++j)
330  {
331  L = k - p + j;
332  for (int i = 0; i <= p - j - s; ++i)
333  {
334  T a = alpha[j - 1][i];
335  tmp.row(i) = a * tmp.row(i + 1) + (1.0 - a) * tmp.row(i);
336  }
337 
338  new_coef.row(new_ind + new_step * L) = tmp.row(0);
339  new_coef.row(new_ind + new_step * (k + r - j - s)) =
340  tmp.row(p - j - s);
341  }
342 
343  // put new control point into proper position
344  for (int i = L + 1; i < k - s; ++i)
345  {
346  new_coef.row(new_ind + step * i) = tmp.row(i - L);
347  }
348 
349  // copy untouched points from the end
350  for (int i = k - s; i < num_of_points; ++i)
351  {
352  new_coef.row(new_ind + (i + r) * step) = coefs.row(ind + i * step);
353  }
354 
355  flag = nextCubePoint<gsVector<int> >(new_position, first_point,
356  new_last_point);
357 
358  } while(nextCubePoint<gsVector<int> >(position, first_point, last_point));
359 
360 
361  coefs = give(new_coef);
362 
363  if (update_knots)
364  {
365  knots.insert(val, r);
366  }
367 }
368 
369 
370 
371 template <typename KnotVectorType, typename Mat, typename ValIt>
373  KnotVectorType& knots,
374  Mat& coefs,
375  int direction,
376  gsVector<unsigned> str,
377  ValIt valBegin,
378  ValIt valEnd,
379  bool update_knots)
380 {
381 
382  typedef typename std::iterator_traits<ValIt>::value_type T;
383 
384  const int npts = coefs.rows(); // number of points
385  const int nik = std::distance(valBegin, valEnd); // number of inserted knots
386  const int nk = knots.size(); // number of knots
387  const int p = knots.degree(); // degree
388  const int d = str.size(); // dimension
389 
390  GISMO_ASSERT(knots[p] <= *valBegin && *(valEnd - 1) <= knots[nk - p - 1],
391  "Can not insert knots, they are out of the knot range");
392  GISMO_ASSERT(direction < d,
393  "We can not insert a knot in a given direction");
394 
395  const int a = knots.iFind(*valBegin) - knots.begin();
396  const int b = (knots.iFind(*(valEnd - 1)) - knots.begin()) + 1;
397 
398  // we compute new coefficients and put them into new_coef
399  int npts_in_dir = nk - p - 1; // number of points in direction d
400  int pts_to_add = (npts / npts_in_dir) * nik; // number of point we must add
401  Mat new_coefs = Mat(npts + pts_to_add, coefs.cols());
402 
403  // allocate a memory for new knots and new control points
404  std::vector<T> nknots(nk + nik);
405 
406  // compute stride for new coefficients
407  gsVector<unsigned> new_str(str);
408  correctNewStride(new_str, str, direction, nik);
409 
410  gsVector<int> position(d); // position old points
411  for (int i = 0; i < d; ++i)
412  position[i] = 0;
413 
414  gsVector<int> new_position(position); // position new points
415  gsVector<int> first_point(position); // first point of a cube
416  gsVector<int> last_point(d); // last point of a cube (old points)
417  gsVector<int> new_last_point(d); // last point of a cube (new points)
418 
419  getLastIndex(str, npts, last_point);
420  getLastIndex(new_str, npts + pts_to_add, new_last_point);
421 
422  last_point[direction] = 0;
423  new_last_point[direction] = 0;
424 
425  int ind, new_ind;
426  const int step = str[direction];
427  const int new_step = new_str[direction];
428  bool flag = true;
429 
430  // precompute alpha
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);
434 
435  do
436  {
437  ValIt valEndCopy = valEnd;
438 
439  if (!flag)
440  GISMO_ERROR("This should not happened! "
441  "We do not have an index for the new matrix.");
442 
443  ind = getIndex(str, position);
444  new_ind = getIndex(new_str, new_position);
445 
446  // copy control points that are not affected
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);
452 
453  // algorithm
454  int i = b + p - 1;
455  int k = b + p + nik - 1; // nik - 1 == r
456 
457  for (int j = nik - 1; 0 <= j; j--)
458  {
459  const T newKnot = *(--valEndCopy);
460  while ((newKnot <= knots[i]) && (a < i))
461  {
462  new_coefs.row(new_ind + (k - p - 1) * new_step) =
463  coefs.row(ind + (i - p - 1) * step);
464  k--;
465  i--;
466  }
467 
468  new_coefs.row(new_ind + (k - p - 1) * new_step) =
469  new_coefs.row(new_ind + (k - p) * new_step);
470 
471  for (int ell = 1; ell <= p; ell++)
472  {
473  const T alfa = alpha[j][ell - 1];
474  const int index = k - p + ell;
475 
476  if (math::abs(alfa) == T(0.0))
477  new_coefs.row(new_ind + (index - 1) * new_step) =
478  new_coefs.row(new_ind + index * new_step);
479  else
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);
483  }
484  k--;
485  }
486 
487  flag = nextCubePoint<gsVector<int> >(new_position, first_point,
488  last_point);
489 
490  } while(nextCubePoint<gsVector<int> >(position, first_point,
491  last_point));
492 
493  coefs = give(new_coefs);
494 
495  if (update_knots)
496  knots = KnotVectorType(p, nknots.begin(), nknots.end());
497 }
498 
499 
500 template <short_t d, typename KnotVectorType, typename Mat, typename ValIt>
501 void gsTensorBoehmRefineLocal(KnotVectorType& knots,
502  const unsigned index,
503  Mat& coefs,
504  gsVector<index_t, d> &nmb_of_coefs,
505  const gsVector<index_t, d> &act_size_of_coefs,
506  const gsVector<index_t, d> &size_of_coefs,
507  const unsigned direction,
508  ValIt valBegin,
509  ValIt valEnd,
510  const bool update_knots)
511 {
512 
513  if (valBegin==valEnd)
514  return;
515 
516  typedef typename std::iterator_traits<ValIt>::value_type T;
517 
518  const index_t nik = std::distance(valBegin, valEnd); // number of inserted knots
519  const index_t p = knots.degree(); // degree
520  // number of original (not local) points
521  const index_t nopts = knots.size() - p - 1;
522  //const int d = size_of_coefs.size(); // dimension
523 
524 
525  const index_t a = knots.iFind(*valBegin) - knots.begin();
526  const index_t b = (knots.iFind(*(valEnd - 1)) - knots.begin()) + 1;
527 
528  // allocate a memory for new knots and new control points
529  gsSparseVector<T> nknots(b + p + nik);
530 
531 
532  gsVector<index_t, d> position(d); // position old points
533  position.fill(0);
534 
535  gsVector<index_t, d> first_point(position); // first point of a cube
536  gsVector<index_t, d> last_point(d); // last point of a cube (old points)
537  bspline::getLastIndexLocal<d>(nmb_of_coefs, last_point);
538  last_point[direction] = 0;
539 
540  // build strides
541  gsVector<index_t, d> act_str(d);
542  bspline::buildCoeffsStrides<d>(act_size_of_coefs, act_str);
543 
544  const index_t step = act_str[direction];
545 
546  gsMatrix<T> zero(1, coefs.cols());
547  zero.fill(0.0);
548 
549 
550  // precompute alpha
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);
554 
555  unsigned iterations = 0;
556  unsigned number_of_iterations = bspline::numberOfIterations(nmb_of_coefs,
557  direction);
558 
559  do
560  {
561  if (number_of_iterations <= iterations)
562  break;
563  ++iterations;
564 
565  ValIt valEndCopy = valEnd;
566 
567  index_t ind = bspline::getIndex<d>(act_str, position);
568 
569  for (index_t j = b - 1; j < nopts; j++)
570  {
571  index_t indx1 = j + nik - index;
572  index_t indx2 = j - index;
573 
574  if (0 <= indx1 &&
575  indx1 < act_size_of_coefs[direction])
576  {
577  if (indx2 < 0)
578  coefs.row(ind + indx1 * step) = zero.row(0);
579  else
580  coefs.row(ind + indx1 * step) =
581  coefs.row(ind + indx2 * step);
582  }
583  }
584 
585 
586  int i = b + p - 1;
587  int k = b + p + nik - 1;
588 
589  for (int j = nik - 1; 0 <= j; j--)
590  {
591  const T newKnot = *(--valEndCopy);
592 
593  while ((newKnot <= knots[i]) && (a < i))
594  {
595  index_t indx1 = k - p - 1 - index;
596  index_t indx2 = i - p - 1 - index;
597 
598  if (indx1 < 0 || act_size_of_coefs[direction] <= indx1)
599  {
600  k--;
601  i--;
602  continue;
603  }
604 
605  if (indx2 < 0)
606  {
607  coefs.row(ind + indx1 * step) = zero.row(0);
608  }
609  else
610  {
611  coefs.row(ind + indx1 * step) =
612  coefs.row(ind + indx2 * step);
613  }
614  k--;
615  i--;
616  }
617 
618  index_t indx1 = k - p - 1 - index;
619 
620  if (0 <= indx1 && (indx1 + 1) < act_size_of_coefs[direction])
621  coefs.row(ind + indx1 * step) =
622  coefs.row(ind + (indx1 + 1) * step);
623 
624  if (indx1 == act_size_of_coefs[direction] - 1)
625  coefs.row(ind + indx1 * step) = zero.row(0);
626 
627  for (int ell = 1; ell <= p; ell++)
628  {
629  const T alfa = alpha[j][ell - 1];
630  const index_t mindex = k - p + ell - index;
631 
632  if (mindex <= 0)
633  continue;
634 
635  if (act_size_of_coefs[direction] < mindex)
636  break;
637 
638  if (math::abs(alfa) == T(0.0))
639  {
640  if (mindex == act_size_of_coefs[direction])
641  coefs.row(ind + (mindex - 1) * step) = zero.row(0);
642  else
643  coefs.row(ind + (mindex - 1) * step) =
644  coefs.row(ind + mindex * step);
645  }
646  else
647  {
648  if (mindex == act_size_of_coefs[direction])
649  coefs.row(ind + (mindex - 1) * step) =
650  alfa * coefs.row(ind + (mindex - 1) * step);
651  else
652  coefs.row(ind + (mindex - 1) * step) =
653  alfa * coefs.row(ind + (mindex - 1) * step) +
654  (1.0 - alfa) * coefs.row(ind + mindex * step);
655  }
656  }
657  k--;
658  }
659  } while(nextCubePoint<gsVector<index_t, d> >(position, first_point,
660  last_point));
661 
662  nmb_of_coefs[direction] = size_of_coefs[direction];
663 
664  if (update_knots)
665  {
666  for (ValIt knot_iter = valBegin; knot_iter != valEnd; ++knot_iter)
667  knots.insert(*knot_iter, 1);
668  }
669 }
670 
671 /*
672 This function performs local Tensor Boehm algorithm. It works.
673 
674 template <short_t d, typename T, typename KnotVectorType, typename Mat>
675 void gsTensorBoehmLocal(
676  const KnotVectorType& knots,
677  unsigned index,
678  Mat& coefs,
679  const gsVector<unsigned, d>& size_of_coefs,
680  const gsVector<unsigned, d>& act_size_of_coefs,
681  T val,
682  unsigned direction,
683  unsigned multiplicity,
684  gsVector<unsigned, d>& start,
685  gsVector<unsigned, d>& end)
686 {
687  int k = knots.findspan(val);
688  int s = knots.multiplicity(val);
689  int p = knots.degree();
690 
691  const unsigned r = multiplicity;
692 
693  std::vector<std::vector<T> > alpha(r, std::vector<T> (p - s));
694  computeAlpha<T, KnotVectorType>(alpha, knots, val, r, k, p, s);
695 
696  // temporary matrix, for computation
697  gsVector<unsigned, d> act_coefs_str(d);
698  bspline::buildCoeffsStrides<d>(act_size_of_coefs, act_coefs_str);
699 
700  start(direction) = 0;
701  end(direction) = 0;
702  gsVector<unsigned, d> position(start);
703 
704 
705  unsigned step = act_coefs_str[direction];
706 
707  do
708  {
709  const unsigned flat_ind = bspline::getIndex<d>(act_coefs_str, position);
710 
711 
712  int low = k - s - index;
713  for (int j = size_of_coefs(direction) - 1; low <= j; --j)
714  coefs.row(flat_ind + (j + r) * step) =
715  coefs.row(flat_ind + j * step);
716 
717  Mat tmp(p + 1, coefs.cols());
718  for (int j = 0; j < p + 1; j++)
719  {
720  tmp.row(j) = coefs.row(flat_ind + (k - p + j - index) * step);
721  }
722 
723  int L = 0;
724  for (unsigned j = 1; j <= r; j++)
725  {
726  L = k - p + j;
727 
728  for (unsigned i = 0; i <= p - j - s; i++)
729  {
730  T alfa = alpha[j - 1][i];
731  tmp.row(i) = alfa * tmp.row(i + 1) + (1.0 - alfa) * tmp.row(i);
732 
733 // if (ind < 0)
734 // continue;
735 // else if (ind == static_cast<int>(act_size_of_coefs(direction)) - 1)
736 // coefs.row(flat_ind + (ind * step) =
737 // (1 - alfa) * coefs.row(flat_ind + ind * step);
738 // else
739 // {
740 // coefs.row(flat_ind + (ind + 1) * step) =
741 // alfa * coefs.row(flat_ind + (ind + 1) * step) +
742 // (1.0 - alfa) * coefs.row(flat_ind + ind * step);
743  // }
744  }
745 
746  coefs.row(flat_ind + (L - index) * step) = tmp.row(0);
747  coefs.row(flat_ind + (k + r - j - s - index) * step) =
748  tmp.row(p - j - s);
749 
750  }
751  } while(nextCubePoint<gsVector<unsigned, d> >(position, start, end));
752 }
753 */
754 
755 
756 template <short_t d, typename T, typename KnotVectorType, typename Mat>
758  const KnotVectorType& knots,
759  Mat& coefs,
760  const gsVector<index_t, d>& size_of_coefs,
761  T val,
762  unsigned direction,
763  gsVector<index_t, d>& start,
765 {
766  int k = knots.iFind(val) - knots.begin();
767  int s = knots.multiplicity(val);
768  int p = knots.degree();
769 
770  // if multiplicity is greater than degree, we insert no knots
771  if (p <= s)
772  return;
773 
774  const unsigned r = p - s; // how many times we will insert the knot val
775 
776  std::vector<std::vector<T> > alpha(r, std::vector<T> (p - s));
777  computeAlpha<T, KnotVectorType>(alpha, knots, val, r, k, p, s);
778 
779  gsVector<index_t, d> coefs_str(d);
780  bspline::buildCoeffsStrides<d>(size_of_coefs, coefs_str);
781 
782  start(direction) = 0;
783  end(direction) = 0;
784  gsVector<index_t, d> position(start);
785 
786  unsigned step = coefs_str[direction];
787 
788  do
789  {
790  const unsigned flat_ind = bspline::getIndex<d>(coefs_str, position);
791  for (unsigned j = 1; j <= r; j++)
792  {
793  for (unsigned i = 0; i <= p - j - s; i++)
794  {
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);
799  }
800  }
801  } while(nextCubePoint<gsVector<index_t, d> >(position, start, end));
802 }
803 
804 } // namespace gismo
void gsBoehm(KnotVectorType &knots, Mat &coefs, T val, int r=1, bool update_knots=true)
Performs insertion of multiple knot on &quot;knots&quot; and coefficients &quot;coefs&quot;.
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 &lt;j&gt; 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 &quot;knots&quot; and coefficients &quot;coefs&quot;.
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