G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsHFitting.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsModeling/gsFitting.h>
18 
19 namespace gismo {
20 
30 template <short_t d, class T>
31 class gsHFitting : public gsFitting<T>
32 {
33 public:
34 
36 
37 public:
39  gsHFitting();
40 
58  gsHFitting(gsMatrix<T> const & param_values,
59  gsMatrix<T> const & points,
60  gsHTensorBasis<d,T> & basis,
61  T refin, const std::vector<unsigned> & extension,
62  T lambda = 0)
63  : gsFitting<T>(param_values, points, basis)
64  {
65  GISMO_ASSERT((refin >=0) && (refin <=1),
66  "Refinement percentage must be between 0 and 1." );
67  GISMO_ASSERT(extension.size() == d, "Extension is not of the right dimension");
68  GISMO_ASSERT( (gsAsConstVector<unsigned>(extension).array()>=0).all(),
69  "Extension must be a positive number.");
70 
71  m_ref = refin; //how many % to refine
72 
73  m_ext = extension;
74 
75  m_lambda = lambda; // Smoothing parameter
76 
78 
79  m_pointErrors.reserve(m_param_values.cols());
80  }
81 
82 public:
83 
97  void iterativeRefine(int iterations, T tolerance, T err_threshold = -1);
98 
104  bool nextIteration(T tolerance, T err_threshold, index_t maxPcIter = 0);
105 
110  bool nextIteration(T tolerance, T err_threshold,
111  const std::vector<boxSide>& fixedSides,
112  index_t maxPcIter = 0);
113 
116  {
117  return m_ref;
118  }
119 
121  const std::vector<unsigned> & get_extension() const
122  {
123  return m_ext;
124  }
125 
127  void setRefPercentage(double refPercent)
128  {
129  GISMO_ASSERT((refPercent >=0) && (refPercent <=1), "Invalid percentage" );
130  m_ref = refPercent;
131  }
132 
134  void setExtension(std::vector<unsigned> const & extension)
135  {
136  GISMO_ASSERT( (gsAsConstVector<unsigned>(extension).array()>=0).all(),
137  "Extension must be a positive number.");
138  GISMO_ASSERT(extension.size()== static_cast<size_t>(this->m_basis.dim()),
139  "Error in dimension");
140  m_ext = extension;
141  }
142 
144  std::vector<index_t> getBoxes(const std::vector<T>& errors,
145  const T threshold);
146 
147 protected:
150  virtual void appendBox(std::vector<index_t>& boxes,
151  std::vector<index_t>& cells,
152  const gsVector<T>& parameter);
153 
155  T setRefineThreshold(const std::vector<T>& errors);
156 
158  static bool isCellAlreadyInserted(const gsVector<index_t, d>& a_cell,
159  const std::vector<index_t>& cells);
160 
162  static void append(std::vector<index_t>& boxes,
163  const gsVector<index_t>& box)
164  {
165  for (index_t col = 0; col != box.rows(); col++)
166  boxes.push_back(box[col]);
167  }
168 
169 protected:
170 
172  T m_ref;
173 
176 
178  std::vector<unsigned> m_ext;
179 
182  using gsFitting<T>::m_basis;
184 
188 };
189 
190 template<short_t d, class T>
191 bool gsHFitting<d, T>::nextIteration(T tolerance, T err_threshold,
192  index_t maxPcIter)
193 {
194  std::vector<boxSide> dummy;
195  return nextIteration(tolerance, err_threshold, dummy, maxPcIter);
196 }
197 
198 template<short_t d, class T>
199 bool gsHFitting<d, T>::nextIteration(T tolerance, T err_threshold,
200  const std::vector<boxSide>& fixedSides,
201  index_t maxPcIter)
202 {
203  // INVARIANT
204  // look at iterativeRefine
205 
206  if ( m_pointErrors.size() != 0 )
207  {
208 
209  if ( m_max_error > tolerance )
210  {
211  // if err_treshold is -1 we refine the m_ref percent of the whole domain
212  T threshold = (err_threshold >= 0) ? err_threshold : setRefineThreshold(m_pointErrors);
213 
214  std::vector<index_t> boxes = getBoxes(m_pointErrors, threshold);
215  if(boxes.size()==0)
216  return false;
217 
218  gsHTensorBasis<d, T>* basis = static_cast<gsHTensorBasis<d,T> *> (this->m_basis);
219  basis->refineElements(boxes);
220 
221  // If there are any fixed sides, prescribe the coefs in the finer basis.
222  if(m_result != NULL && fixedSides.size() > 0)
223  {
224  m_result->refineElements(boxes);
225  gsFitting<T>::setConstraints(fixedSides);
226  }
227  gsDebug << "inserted " << boxes.size() / (2 * d + 1) << " boxes.\n";
228  }
229  else
230  {
231  gsDebug << "Tolerance reached.\n";
232  return false;
233  }
234  }
235 
236  // We run one fitting step and compute the errors
237  this->compute(m_lambda);
238 
239  //parameter correction
240  this->parameterCorrection(1e-7, maxPcIter, 1e-4);//closestPoint accuracy, orthogonality tolerance
241 
242  this->computeErrors();
243 
244  return true;
245 }
246 
247 template<short_t d, class T>
248 void gsHFitting<d, T>::iterativeRefine(int numIterations, T tolerance, T err_threshold)
249 {
250  // INVARIANT:
251  // m_pointErrors contains the point-wise errors of the fitting
252  // therefore: if the size of m_pointErrors is 0, there was no fitting up to this point
253 
254  if ( m_pointErrors.size() == 0 )
255  {
256  this->compute(m_lambda);
257  this->computeErrors();
258  }
259 
260  bool newIteration;
261  for( int i = 0; i < numIterations; i++ )
262  {
263  newIteration = nextIteration( tolerance, err_threshold );
264  if( m_max_error <= tolerance )
265  {
266  gsDebug << "Tolerance reached at iteration: " << i << "\n";
267  break;
268  }
269  if( !newIteration )
270  {
271  gsDebug << "No more Boxes to insert at iteration: " << i << "\n";
272  break;
273  }
274  }
275 }
276 
277 template <short_t d, class T>
278 std::vector<index_t> gsHFitting<d, T>::getBoxes(const std::vector<T>& errors,
279  const T threshold)
280 {
281  // cells contains lower corners of elements marked for refinment from maxLevel
282  std::vector<index_t> cells;
283 
284  // boxes contains elements marked for refinement from differnet levels,
285  // format: { level lower-corners upper-corners ... }
286  std::vector<index_t> boxes;
287 
288  for (size_t index = 0; index != errors.size(); index++)
289  {
290  if (threshold <= errors[index])
291  {
292  appendBox(boxes, cells, this->m_param_values.col(index));
293  }
294  }
295 
296  return boxes;
297 }
298 
299 template <short_t d, class T>
300 void gsHFitting<d, T>::appendBox(std::vector<index_t>& boxes,
301  std::vector<index_t>& cells,
302  const gsVector<T>& parameter)
303 {
304  gsTHBSplineBasis<d, T>* basis = static_cast< gsTHBSplineBasis<d,T>* > (this->m_basis);
305  const int maxLvl = basis->maxLevel();
306  const tensorBasis & tBasis = *(basis->getBases()[maxLvl]);
307 
308  // get a cell
309  gsVector<index_t, d> a_cell;
310 
311  for (short_t dim = 0; dim != d; dim++)
312  {
313  const gsKnotVector<T> & kv = tBasis.component(dim).knots();
314  a_cell(dim) = kv.uFind(parameter(dim)).uIndex();
315  }
316 
317  if (!isCellAlreadyInserted(a_cell, cells))
318  {
319  append(cells, a_cell);
320 
321  // get level of a cell
322  gsVector<index_t, d> a_cell_upp = a_cell + gsVector<index_t, d>::Ones();
323  const int cell_lvl = basis->tree().query3(a_cell, a_cell_upp, maxLvl) + 1;
324 
325  // get the box
326  gsVector<index_t> box(2 * d + 1);
327  box[0] = cell_lvl;
328  for (short_t dim = 0; dim != d; dim++)
329  {
330  const unsigned numBreaks = basis->numBreaks(cell_lvl, dim) - 1 ;
331 
332  unsigned lowIndex = 0;
333  if (cell_lvl < maxLvl)
334  {
335  const unsigned shift = maxLvl - cell_lvl;
336  lowIndex = (a_cell(dim) >> shift);
337  }
338  else
339  {
340  const unsigned shift = cell_lvl - maxLvl;
341  lowIndex = (a_cell(dim) << shift);
342  }
343 
344  // apply extensions
345  index_t low = ( (lowIndex > m_ext[dim]) ? (lowIndex - m_ext[dim]) : 0 );
346  index_t upp = ( (lowIndex + m_ext[dim] + 1 < numBreaks) ?
347  (lowIndex + m_ext[dim] + 1) : numBreaks );
348 
349  box[1 + dim ] = low;
350  box[1 + d + dim] = upp;
351  }
352 
353  append(boxes, box);
354  }
355 }
356 
357 
358 template <short_t d, class T>
360  const std::vector<index_t>& cells)
361 {
362 
363  for (size_t i = 0; i != cells.size(); i += a_cell.rows())
364  {
365  index_t commonEntries = 0;
366  for (index_t col = 0; col != a_cell.rows(); col++)
367  {
368  if (cells[i + col] == a_cell[col])
369  {
370  commonEntries++;
371  }
372  }
373 
374  if (commonEntries == a_cell.rows())
375  {
376  return true;
377  }
378  }
379 
380  return false;
381 }
382 
383 template<short_t d, class T>
384 T gsHFitting<d, T>::setRefineThreshold(const std::vector<T>& errors )
385 {
386  std::vector<T> errorsCopy = errors;
387  const size_t i = cast<T,size_t>(errorsCopy.size() * (1.0 - m_ref));
388  typename std::vector<T>::iterator pos = errorsCopy.begin() + i;
389  std::nth_element(errorsCopy.begin(), pos, errorsCopy.end());
390  return *pos;
391 }
392 
393 
394 }// namespace gismo
395 
396 // #ifndef GISMO_BUILD_LIB
397 // #include GISMO_HPP_HEADER(gsFitting.hpp)
398 // #endif
Provides definition of HTensorBasis abstract interface.
const std::vector< unsigned > & get_extension() const
Returns the chosen cell extension.
Definition: gsHFitting.h:121
T getRefPercentage() const
Return the refinement percentage.
Definition: gsHFitting.h:115
void setConstraints(const gsSparseMatrix< T > &lhs, const gsMatrix< T > &rhs)
Definition: gsFitting.h:133
gsHFitting(gsMatrix< T > const &param_values, gsMatrix< T > const &points, gsHTensorBasis< d, T > &basis, T refin, const std::vector< unsigned > &extension, T lambda=0)
Main constructor of the fitting class.
Definition: gsHFitting.h:58
static bool isCellAlreadyInserted(const gsVector< index_t, d > &a_cell, const std::vector< index_t > &cells)
Checks if a_cell is already inserted in container of cells.
Definition: gsHFitting.h:359
#define gsDebug
Definition: gsDebug.h:61
#define short_t
Definition: gsConfig.h:35
bool nextIteration(T tolerance, T err_threshold, index_t maxPcIter=0)
nextIteration One step of the refinement of iterative_refine(...);
Definition: gsHFitting.h:191
Provides declaration of data fitting algorithms by least squares approximation.
#define index_t
Definition: gsConfig.h:32
T m_ref
How many % to refine - 0-1 interval.
Definition: gsHFitting.h:172
const std::vector< tensorBasis * > & getBases() const
Returns the tensor B-spline space of all levels.
Definition: gsHTensorBasis.h:425
const gsHDomain< d > & tree() const
Returns a reference to m_tree.
Definition: gsHTensorBasis.h:601
T m_lambda
Smoothing parameter.
Definition: gsHFitting.h:175
A tensor product B-spline basis.
Definition: gsTensorBSplineBasis.h:36
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
uiterator uFind(const T u) const
Returns the uiterator pointing to the knot at the beginning of the knot interval containing u...
Definition: gsKnotVector.hpp:747
static void append(std::vector< index_t > &boxes, const gsVector< index_t > &box)
Appends a box to the end of boxes (This function also works for cells)
Definition: gsHFitting.h:162
Class for performing a least squares fit of a parametrized point cloud with a gsGeometry.
Definition: gsFitting.h:32
Class representing a (scalar) hierarchical tensor basis of functions .
Definition: gsHTensorBasis.h:74
gsHFitting()
Default constructor.
int query3(point const &k1, point const &k2, int level, node *_node) const
Definition: gsHDomain.hpp:448
virtual void refineElements(std::vector< index_t > const &boxes)
Insert the given boxes into the quadtree.
Definition: gsHTensorBasis.hpp:843
std::vector< index_t > getBoxes(const std::vector< T > &errors, const T threshold)
Returns boxes which define refinment area.
Definition: gsHFitting.h:278
void setExtension(std::vector< unsigned > const &extension)
Sets the cell extension.
Definition: gsHFitting.h:134
void setRefPercentage(double refPercent)
Sets the refinement percentage.
Definition: gsHFitting.h:127
gsFunctionSet< T > * m_basis
Pointer keeping the basis.
Definition: gsFitting.h:176
unsigned maxLevel() const
Returns the level in which the indices are stored internally.
Definition: gsHTensorBasis.h:811
void iterativeRefine(int iterations, T tolerance, T err_threshold=-1)
iterative_refine iteratively refine the basis
Definition: gsHFitting.h:248
gsMatrix< T > m_param_values
the parameter values of the point cloud
Definition: gsFitting.h:167
Class for representing a knot vector.
Definition: gsKnotVector.h:79
Creates a mapped object or data pointer to a const vector without copying data.
Definition: gsLinearAlgebra.h:130
virtual void appendBox(std::vector< index_t > &boxes, std::vector< index_t > &cells, const gsVector< T > &parameter)
Definition: gsHFitting.h:300
std::vector< unsigned > m_ext
Size of the extension.
Definition: gsHFitting.h:178
T m_min_error
Minimum point-wise error.
Definition: gsFitting.h:193
Truncated hierarchical B-spline basis.
Definition: gsTHBSplineBasis.h:35
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
T setRefineThreshold(const std::vector< T > &errors)
Identifies the threshold from where we should refine.
Definition: gsHFitting.h:384
GISMO_DEPRECATED bool parameter(int s)
Returns the parameter value (false=0=start, true=1=end) that corresponds to side s.
Definition: gsBoundary.h:1069
This class applies hierarchical fitting of parametrized point clouds.
Definition: gsHFitting.h:31
T m_max_error
Maximum point-wise error.
Definition: gsFitting.h:190
int numBreaks(int lvl, int k) const
Definition: gsHTensorBasis.h:436