G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsHDomain.hpp
Go to the documentation of this file.
1 
15 #include <gsHSplines/gsVSegment.h>
16 #include <gsHSplines/gsKdNode.h>
17 #include <gsCore/gsLinearAlgebra.h>
18 #include <gsCore/gsBoundary.h>
19 
20 #include <queue>
21 
22 namespace
23 {
24  // Query 1
25  struct query1_visitor
26  {
27  typedef bool return_type;
28 
29  // initialize result as true
30  static return_type init() {return true;}
31 
32  template<short_t d, class Z>
33  static void visitLeaf(gismo::gsKdNode<d, Z> * leafNode , int level, return_type & res)
34  {
35  if ( leafNode->level != level )
36  res = false;
37  }
38  };
39 
40  // Query 2
41  struct query2_visitor
42  {
43  typedef bool return_type;
44 
45  // initialize result as true
46  static return_type init() {return true;}
47 
48  template<short_t d, class Z>
49  static void visitLeaf(gismo::gsKdNode<d, Z> * leafNode , int level, return_type & res)
50  {
51  if ( leafNode->level <= level )
52  res = false;
53  }
54  };
55 
56  // Query 3
57  struct query3_visitor
58  {
59  typedef int return_type;
60 
61  // initialize result as a max possible value, since we are looking
62  // for a minimum
63  static return_type init() {return 1000000;}
64 
65  template<short_t d, class Z>
66  static void visitLeaf(gismo::gsKdNode<d, Z> * leafNode , int , return_type & res)
67  {
68  if ( leafNode->level < res )
69  res = leafNode->level;
70  }
71  };
72 
73  // Query 4
74  struct query4_visitor
75  {
76  typedef int return_type;
77 
78  // initialize result as a minimum possible value, since we are
79  // looking for a maximum
80  static return_type init() {return -1;}
81 
82  template<short_t d, class Z>
83  static void visitLeaf(gismo::gsKdNode<d, Z> * leafNode , int , return_type & res)
84  {
85  if ( leafNode->level > res )
86  res = leafNode->level;
87  }
88  };
89 
90 } //namespace
91 
92 namespace gismo {
93 
94 
95 template<short_t d, class Z>
97 {
98  return new gsHDomain(*this);
99 }
100 
101 
102 template<short_t d, class Z>
103 inline bool gsHDomain<d, Z>::haveOverlap(box const & box1, box const & box2)
104 {
105  return !( (box1.second.array() <= box1.first .array()).any() ||
106  (box2.first .array() >= box1.second.array()).any() );
107 }
108 
109 template<short_t d, class Z>
110 inline bool gsHDomain<d, Z>::isContained(box const & box1, box const & box2)
111 {
112  return !( (box1.first .array() < box2.first .array()).any() ||
113  (box1.second.array() > box2.second.array()).any() ) ;
114 }
115 
116 template<short_t d, class Z> void
118 {
119  // to do: non-recc.
120  if ( _node->isLeaf() )
121  {
122  // if the level in the *_node is smaller the value of lvl we
123  // modify it
124  _node->level = lvl;
125  }
126  else
127  {
128  // we call the function set level for all existing children of
129  // the node *_node
130  setLevel(_node->left , lvl);
131  setLevel(_node->right, lvl);
132  }
133 }
134 
135 template<short_t d, class Z> inline bool
137 {
138  return (someBox.first.array() >= someBox.second.array()).any() ;
139 }
140 
141 //use "surface area heuristic" (SAH) ?
142 template<short_t d, class Z> void
143 gsHDomain<d, Z>::insertBox ( point const & k1, point const & k2,
144  node *_node, int lvl) // CONSTRAINT: lvl is "minimum level"
145 {
146  GISMO_ENSURE( lvl <= static_cast<int>(m_indexLevel), "Max index level reached..");
147 
148  // Make a box
149  box iBox(k1,k2);
150  if( isDegenerate(iBox) )
151  return;
152 
153  // Represent box in the index level
154  // iBox.first .unaryExpr(toGlobalIndex(lvl, m_index_level) );
155  // iBox.second.unaryExpr(toGlobalIndex(lvl, m_index_level) );
156  local2globalIndex( iBox.first , static_cast<unsigned>(lvl), iBox.first );
157  local2globalIndex( iBox.second, static_cast<unsigned>(lvl), iBox.second);
158 
159  // Ensure that the box is within the valid limits
160  if ( ( iBox.first.array() >= m_upperIndex.array() ).any() )
161  {
162  gsWarn<<" Invalid box coordinate "<< k1.transpose() <<" at level" <<lvl<<".\n";
163  return;
164  }
165 
166  // Initialize stack
167  std::vector<node*> stack;
168  stack.reserve( 2 * (m_maxPath + d) );
169  stack.push_back(_node); //push(_node);
170 
171  node * curNode;
172  while ( ! stack.empty() )
173  {
174  curNode = stack.back(); //top();
175  stack.pop_back(); //pop();
176 
177  if ( curNode->isLeaf() ) // reached a leaf
178  {
179  // Since we reached a leaf, it should overlap with iBox
180 
181  // If this leaf is already in level lvl, then we have nothing to do
182  if ( lvl <= curNode->level )
183  continue;
184 
185  // Split the leaf (if possible)
186  //node * newLeaf = curNode->adaptiveSplit(iBox);
187  node * newLeaf = curNode->adaptiveAlignedSplit(iBox, m_indexLevel);
188 
189  // If curNode is still a leaf, its domain is almost
190  // contained in iBox
191  if ( !newLeaf ) // curNode->isLeaf()
192  {
193  // Increase level and reccurse
194  if ( ++curNode->level != lvl)
195  stack.push_back(curNode);
196  }
197  else // treat new child
198  {
199  stack.push_back(newLeaf);
200  }
201  }
202  else // roll down the tree
203  {
204  if ( iBox.second[curNode->axis] <= curNode->pos)
205  // iBox overlaps only left child of this split-node
206  stack.push_back(curNode->left);
207  else if ( iBox.first[curNode->axis] >= curNode->pos)
208  // iBox overlaps only right child of this split-node
209  stack.push_back(curNode->right);
210  else
211  {
212  // iBox overlaps both children of this split-node
213  stack.push_back(curNode->left );
214  stack.push_back(curNode->right);
215  }
216  }
217  }
218 
219  // Update maximum inserted level
220  if ( static_cast<unsigned>(lvl) > m_maxInsLevel)
221  m_maxInsLevel = lvl;
222 }
223 
224 template<short_t d, class Z> void
225 gsHDomain<d, Z>::clearBox ( point const & k1, point const & k2,
226  int lvl) // CONSTRAINT: lvl is "minimum level"
227 {
228  GISMO_ENSURE( lvl <= static_cast<int>(m_indexLevel), "Max index level reached..");
229 
230  // Make a box
231  box iBox(k1,k2);
232  if( isDegenerate(iBox) )
233  return;
234 
235  // Represent box in the index level
236  // iBox.first .unaryExpr(toGlobalIndex(lvl, m_index_level) );
237  // iBox.second.unaryExpr(toGlobalIndex(lvl, m_index_level) );
238  local2globalIndex( iBox.first , static_cast<unsigned>(lvl), iBox.first );
239  local2globalIndex( iBox.second, static_cast<unsigned>(lvl), iBox.second);
240 
241  // Ensure that the box is within the valid limits
242  if ( ( iBox.first.array() >= m_upperIndex.array() ).any() )
243  {
244  gsWarn<<" Invalid box coordinate "<< k1.transpose() <<" at level" <<lvl<<".\n";
245  return;
246  }
247 
248  // Initialize stack
249  std::vector<node*> stack;
250  stack.reserve( 2 * (m_maxPath + d) );
251  stack.push_back(m_root); //push(m_root);
252 
253  node * curNode;
254  while ( ! stack.empty() )
255  {
256  curNode = stack.back(); //top();
257  stack.pop_back(); //pop();
258 
259  if ( curNode->isLeaf() ) // reached a leaf
260  {
261  // Since we reached a leaf, it should overlap with iBox
262 
263  // If this leaf is already in level lvl, then we have nothing to do
264  if ( curNode->level <= lvl )
265  continue;
266 
267  // Split the leaf (if possible)
268  node * newLeaf = curNode->adaptiveAlignedSplit(iBox, m_indexLevel);
269 
270  // If curNode is still a leaf, its domain is almost
271  // contained in iBox
272  if ( !newLeaf ) // curNode->isLeaf()
273  {
274  // Decrease level and reccurse
275  if ( --curNode->level != lvl)
276  stack.push_back(curNode);
277  }
278  else // treat new child
279  {
280  stack.push_back(newLeaf);
281  }
282  }
283  else // roll down the tree
284  {
285  if ( iBox.second[curNode->axis] <= curNode->pos)
286  // iBox overlaps only left child of this split-node
287  stack.push_back(curNode->left);
288  else if ( iBox.first[curNode->axis] >= curNode->pos)
289  // iBox overlaps only right child of this split-node
290  stack.push_back(curNode->right);
291  else
292  {
293  // iBox overlaps both children of this split-node
294  stack.push_back(curNode->left );
295  stack.push_back(curNode->right);
296  }
297  }
298  }
299 
300  computeMaxInsLevel(); // compute again globally
301 }
302 
303 template<short_t d, class Z> void
305  point const & k2, int lvl)
306 {
307  GISMO_ENSURE( m_maxInsLevel+1 <= m_indexLevel,
308  "Max index level might be reached..");
309 
310  // Make a box
311  box iBox(k1,k2);
312  if( isDegenerate(iBox) )
313  return;
314 
315  // Represent box in the index level
316  local2globalIndex( iBox.first , static_cast<unsigned>(lvl), iBox.first );
317  local2globalIndex( iBox.second, static_cast<unsigned>(lvl), iBox.second);
318 
319  // Ensure that the box is within the valid limits
320  if ( ( iBox.first.array() >= m_upperIndex.array() ).any() )
321  {
322  //gsWarn<<" Invalid box coordinate "<< k1.transpose() <<" at level" <<lvl<<".\n";
323  return;
324  }
325 
326  // Initialize stack
327  std::stack<node*, std::vector<node*> > stack;
328  stack.push(m_root);
329 
330  node * curNode;
331  while ( ! stack.empty() )
332  {
333  curNode = stack.top();
334  stack.pop();
335 
336  if ( curNode->isLeaf() ) // reached a leaf
337  {
338  // Since we reached a leaf, it should overlap with iBox.
339  // Split the leaf (if possible)
340  node * newLeaf = curNode->adaptiveAlignedSplit(iBox, m_indexLevel);
341 
342  // If curNode is still a leaf, its domain is almost
343  // contained in iBox
344  if ( !newLeaf ) // implies curNode was a leaf
345  {
346  // Increase level
347  if ( ++curNode->level > static_cast<int>(m_maxInsLevel) )
348  m_maxInsLevel = curNode->level;
349  }
350  else // treat new child
351  {
352  stack.push(newLeaf);
353  }
354  }
355  else // walk down the tree
356  {
357  if ( iBox.second[curNode->axis] <= curNode->pos)
358  // iBox overlaps only left child of this split-node
359  stack.push(curNode->left);
360  else if ( iBox.first[curNode->axis] >= curNode->pos)
361  // iBox overlaps only right child of this split-node
362  stack.push(curNode->right);
363  else
364  {
365  // iBox overlaps both children of this split-node
366  stack.push(curNode->left );
367  stack.push(curNode->right);
368  }
369  }
370  }
371 }
372 
373 template<short_t d, class Z>
375 {
376  std::stack<node*, std::vector<node*> > tstack;
377  node * curNode;
378 
379  // First step: gather all terminal nodes
380  std::stack<node*, std::vector<node*> > stack;
381  stack.push(m_root);
382  while ( ! stack.empty() )
383  {
384  curNode = stack.top();
385  stack.pop();
386 
387  if ( curNode->isTerminal() )
388  {
389  // Remember this terminal node
390  tstack.push(curNode);
391  }
392  else if ( ! curNode->isLeaf() ) // this is a non-terminal split-node
393  {
394  stack.push(curNode->left );
395  stack.push(curNode->right);
396  }
397  }
398 
399  // Second step: reccursively merge siblings that have the same level
400  while ( ! tstack.empty() )
401  {
402  curNode = tstack.top();
403  tstack.pop();
404 
405  if (curNode->left->level == curNode->right->level)
406  {
407  // Merge left and right
408  curNode->merge();
409  if ( !curNode->isRoot() &&
410  curNode->parent->isTerminal() )
411  tstack.push(curNode->parent );
412  }
413  }
414 
415  // Store the max path length
416  m_maxPath = minMaxPath().second;
417 }
418 
419 template<short_t d, class Z>
420 bool gsHDomain<d, Z>::query1(point const & lower, point const & upper,
421  int level, node *_node) const
422 {
423  return boxSearch< query1_visitor >(upper,lower,level,_node);
424 }
425 
426 template<short_t d, class Z>
427 bool gsHDomain<d, Z>::query1(point const & lower, point const & upper,
428  int level) const
429 {
430  return boxSearch< query1_visitor >(upper,lower,level,m_root);
431 }
432 
433 template<short_t d, class Z>
434 bool gsHDomain<d, Z>::query2(point const & lower, point const & upper,
435  int level, node *_node) const
436 {
437  return boxSearch< query2_visitor >(lower,upper,level,_node);
438 }
439 
440 template<short_t d, class Z>
441 bool gsHDomain<d, Z>::query2 (point const & lower, point const & upper,
442  int level) const
443 {
444  return boxSearch< query2_visitor >(lower,upper,level,m_root);
445 }
446 
447 template<short_t d, class Z>
448 int gsHDomain<d, Z>::query3(point const & lower, point const & upper,
449  int level, node *_node) const
450 {
451  return boxSearch< query3_visitor >(lower,upper,level,_node);
452 }
453 
454 template<short_t d, class Z>
455 int gsHDomain<d, Z>::query3(point const & lower, point const & upper,
456  int level) const
457 {
458  return boxSearch< query3_visitor >(lower,upper,level,m_root);
459 }
460 
461 template<short_t d, class Z>
462 int gsHDomain<d, Z>::query4(point const & lower, point const & upper,
463  int level, node *_node) const
464 {
465  return boxSearch< query4_visitor >(lower,upper,level,_node);
466 }
467 
468 template<short_t d, class Z>
469 int gsHDomain<d, Z>::query4(point const & lower, point const & upper,
470  int level) const
471 {
472  return boxSearch< query4_visitor >(lower,upper,level,m_root);
473 }
474 
475 template<short_t d, class Z>
476 std::pair<typename gsHDomain<d, Z>::point, typename gsHDomain<d, Z>::point>
477 gsHDomain<d, Z>::queryLevelCell(point const & lower, point const & upper,
478  int level) const
479 {
480  std::pair<point,point> tmp = boxSearch< get_cell_visitor >(lower,upper,level,m_root);
481  global2localIndex(tmp.first,level,tmp.first);
482  global2localIndex(tmp.second,level,tmp.second);
483  return tmp;
484 }
485 
486 template<short_t d, class Z>
487 std::pair<typename gsHDomain<d, Z>::point, typename gsHDomain<d, Z>::point>
488 gsHDomain<d, Z>::select_part(point const & k1, point const & k2,
489  point const & k3, point const & k4)
490 {
491  // intersect boxes
492  std::pair<point,point> result;
493 
494  for( short_t i = 0; i<d; ++i)
495  {
496  //find the lower left corner
497  result.first[i] = ( k1[i] >= k3[i] ? k1[i] : k3[i] );
498  //find the upper right corner
499  result.second[i] = ( k2[i] >= k4[i] ? k4[i] : k2[i] );
500  }
501  return result;
502 }
503 
504 template<short_t d, class Z> void
505 gsHDomain<d, Z>::bisectBox(box const & original, int k, Z coord,
506  box & leftBox, box & rightBox )
507 {
508  GISMO_ASSERT( ! isDegenerate(original) , "Invalid box .");
509  GISMO_ASSERT( (k>=0) && (k< static_cast<int>(d)) , "Invalid axis "<< k <<".");
510  leftBox = rightBox = original;
511  leftBox.second[k] = rightBox.first[k] = coord;
512 }
513 
514 
515 template<short_t d, class Z>
516 template<typename visitor>
517 typename visitor::return_type
518 gsHDomain<d, Z>::boxSearch(point const & k1, point const & k2,
519  int level, node *_node ) const
520 {
521  // Make a box
522  box qBox(k1,k2);
523  local2globalIndex( qBox.first , static_cast<unsigned>(level), qBox.first );
524  local2globalIndex( qBox.second, static_cast<unsigned>(level), qBox.second);
525 
526  GISMO_ASSERT( !isDegenerate(qBox),
527  "boxSearch: Wrong order of points defining the box (or empty box): "
528  << qBox.first.transpose() <<", "<< qBox.second.transpose() <<".\n" );
529 
530  typename visitor::return_type res = visitor::init();
531 
532  std::vector<node*> stack;
533  stack.reserve( 2 * m_maxPath );
534  stack.push_back(_node); //push(_node);
535 
536  node * curNode;
537  while ( ! stack.empty() )
538  {
539  curNode = stack.back(); //top();
540  stack.pop_back(); //pop();
541 
542  if ( curNode->isLeaf() )
543  {
544  // Visit the leaf
545  GISMO_ASSERT( !isDegenerate(*curNode->box), "Encountered an empty leaf");
546  visitor::visitLeaf(curNode, level, res );
547  }
548  else // this is a split-node
549  {
550  if ( qBox.second[curNode->axis] <= curNode->pos)
551  // qBox overlaps only left child of this split-node
552  stack.push_back(curNode->left); //push(curNode->left);
553  else if ( qBox.first[curNode->axis] >= curNode->pos)
554  // qBox overlaps only right child of this split-node
555  stack.push_back(curNode->right); //push(curNode->right);
556  else
557  {
558  // qBox overlaps both children of this split-node
559  stack.push_back(curNode->left ); //push(curNode->left );
560  stack.push_back(curNode->right); //push(curNode->right);
561  }
562  }
563  }
564 
565  return res;
566 }
567 
568 
569 
570 template<short_t d, class Z>
571 typename gsHDomain<d, Z>::node *
572 gsHDomain<d, Z>::pointSearch(const point & p, int level, node *_node ) const
573 {
574  point pp;
575  local2globalIndex(p, static_cast<unsigned>(level), pp);
576 
577  GISMO_ASSERT( ( pp.array() <= m_upperIndex.array() ).all(),
578  "pointSearch: Wrong input: "<< p.transpose()<<", level "<<level<<".\n" );
579 
580  std::vector<node*> stack;
581  stack.reserve( 2 * m_maxPath );
582  stack.push_back(_node);
583 
584  node * curNode;
585  while ( ! stack.empty() )
586  {
587  curNode = stack.back(); //top();
588  stack.pop_back(); //pop();
589 
590  if ( curNode->isLeaf() )
591  {
592  // Point found at current node
593  return curNode;
594  }
595  else // this is a split-node
596  {
597  if ( pp[curNode->axis] < curNode->pos)
598  stack.push_back(curNode->left);
599  else
600  stack.push_back(curNode->right);
601  }
602  }
603  GISMO_ERROR("pointSearch: Error ("<< p.transpose()<<").\n" );
604 }
605 
606 
607 template<short_t d, class Z>
608 template<typename visitor>
609 typename visitor::return_type
611 {
612  typename visitor::return_type i = visitor::init();
613 
614  node * curNode = m_root;
615 
616  while(true)
617  {
618  visitor::visitNode(curNode, i);
619 
620  if ( !curNode->isLeaf() )
621  { //property: tree has no singles
622  curNode = curNode->left;
623  }
624  else
625  {
626  while (curNode->parent != NULL &&
627  curNode != curNode->parent->left)
628  curNode = curNode->parent;
629 
630  if ( curNode->isRoot() )
631  break;
632  else
633  curNode = curNode->parent->right;
634  }
635  }
636  return i;
637 }
638 
639 template<short_t d, class Z>
640 template<typename visitor>
641 typename visitor::return_type
643 {
644  typename visitor::return_type i = visitor::init();
645 
646  node * curNode = m_root;
647 
648  while(true)
649  {
650  if ( !curNode->isLeaf() )
651  { //property: tree has no singles (only childs)
652  curNode = curNode->left;
653  }
654  else
655  {
656  // Visit the leaf
657  visitor::visitLeaf(curNode, i);
658 
659  while (curNode->parent != NULL &&
660  curNode != curNode->parent->left)
661  curNode = curNode->parent;
662 
663  if ( curNode->isRoot() )
664  break;
665  else
666  curNode = curNode->parent->right;
667  }
668  }
669  return i;
670 }
671 
672 
673 template<short_t d, class Z>
674 std::pair<int,int>
676 {
677  node * curNode = m_root;
678  int min = 1000000000, max = -1, cur = 0;
679 
680  while(true)
681  {
682  if ( !curNode->isLeaf() )
683  { //property: tree has no singles
684  curNode = curNode->left;
685  cur++;
686  }
687  else
688  {
689  // Update min-max
690  min = math::min(min,cur);
691  max = math::max(max,cur);
692 
693  while (curNode->parent != NULL &&
694  curNode != curNode->parent->left)
695  {
696  curNode = curNode->parent;
697  cur--;
698  }
699 
700  if ( curNode->isRoot() )
701  break;
702  else
703  curNode = curNode->parent->right;
704  }
705  }
706  return std::make_pair(min,max);
707 }
708 
709 template<short_t d, class Z>
711 {
712  std::vector<std::vector<Z> > boxes;
713 
714  // get all boxes in vector-format
715  getBoxes_vec(boxes);
716 
717  // connect boxes which have the same levels and are
718  // are aligned such that their union again is an
719  // axis-aligned box.
720  connect_Boxes(boxes);
721 
722  // write the result into b1, b2, and level
723  b1.resize(boxes.size(),d);
724  b2.resize(boxes.size(),d);
725  level.resize(boxes.size());
726  for(size_t i = 0; i < boxes.size(); i++)
727  {
728  for(short_t j = 0; j < d; j++)
729  {
730  b1(i,j) = boxes[i][j];
731  b2(i,j) = boxes[i][j+d];
732  }
733  level[i] = boxes[i][2*d];
734  }
735 }
736 
737 
738 template<short_t d, class Z>
740 {
741 
742  getBoxes( b1, b2, level);
743  std::vector<Z> onSide;
744 
745  unsigned remainder = (s-1) % 2;
746  // remainder will be
747  // 0 for sides 1 (west), 3 (south/down), or 5 (front)
748  // 1 for sides 2 (east), 4 (north/up), or 6 (back)
749  unsigned quotient = ( (s-1) - remainder ) / 2;
750  // quotient will be
751  // 0 for east/west
752  // 1 for south/north or down/up
753  // 2 for front/back
754 
755  if( remainder == 0 ) // sides 1 (west), 3 (south/down), or 5 (front)
756  {
757  // if a box touches
758  for(index_t i = 0; i < b1.rows(); i++)
759  if( b1(i, quotient ) == 0 )
760  onSide.push_back(i);
761  }
762  else // remainder == 1, sides east, north/up, or back
763  {
764  for(index_t i = 0; i < b1.rows(); i++)
765  {
766  // index of upper corner
767  Z B2( b2(i, quotient ) );
768  // transform to index-level
769  B2 = B2 << (m_indexLevel - m_maxInsLevel);
770 
771  // check if this index is on the boundary
772  if( B2 == m_upperIndex[ quotient ] )
773  onSide.push_back( i );
774  }
775  }
776 
777  // select only the boxes on side s:
778  for(size_t i=0; i < onSide.size(); i++)
779  {
780  b1.row(i) = b1.row( onSide[i] );
781  b2.row(i) = b2.row( onSide[i] );
782  level[i] = level( onSide[i] );
783  }
784  b1.conservativeResize( onSide.size(), b1.cols() );
785  b2.conservativeResize( onSide.size(), b2.cols() );
786  level.conservativeResize( onSide.size() );
787 }
788 
789 template<short_t d, class Z>
791  gsMatrix<Z>& b2,
792  gsVector<index_t>& level) const
793 {
794  std::vector<std::vector<Z> > boxes;
795  getBoxes_vec(boxes);
796  GISMO_ASSERT(d==2 || d==3, "Wrong dimension, should be 2 or 3.");
797  //is this test really necessary? florian b.
798  for(size_t i = 0; i < boxes.size(); i++)
799  {
800  if ((boxes[i][0]==boxes[i][d+0]) || (boxes[i][1]==boxes[i][1+d]))
801  {
802  boxes.erase(boxes.begin()+i);
803  i--;
804  }
805  else if((d == 3) && (boxes[i][2]==boxes[i][d+2]))
806  {
807  boxes.erase(boxes.begin()+i);
808  i--;
809  }
810  }
811  gsVector<Z, d> lowerCorner;
812  gsVector<Z, d> upperCorner;
813  connect_Boxes(boxes);
814  b1.resize(boxes.size(), d);
815  b2.resize(boxes.size(), d);
816  level.resize(boxes.size());
817  for(size_t i = 0; i < boxes.size(); i++)
818  {
819  for(short_t j = 0; j < d; j++)
820  {
821  lowerCorner[j] = boxes[i][j];
822  upperCorner[j] = boxes[i][j+d];
823  }
824  level[i] = boxes[i][2*d];
825  computeLevelIndex(lowerCorner, level[i], lowerCorner);
826  computeLevelIndex(upperCorner, level[i], upperCorner);
827  b1.row(i) = lowerCorner;
828  b2.row(i) = upperCorner;
829  }
830 }
831 
832 // Old version that only works for 2D
833 // Should be replaced by the "new" connect_Boxes.
834 // Keeping the code for the moment, in order not to loose
835 // the old code before the new one is properly tested.
836 template<short_t d, class Z> void
837 gsHDomain<d, Z>::connect_Boxes2d(std::vector<std::vector<Z>> &boxes) const
838 {
839  GISMO_ASSERT( d == 2, "This one only works for 2D");
840  bool change = true;
841  while(change)
842  {
843  change = false;
844  size_t s = boxes.size();
845  for(size_t i = 0; i < s; i++)
846  {
847  for(size_t j = i+1; j < s; j++)
848  {
849  // if the levels are the same:
850  if(boxes[i][4]==boxes[j][4])
851  {
852  if( (boxes[i][0]==boxes[j][0]) && (boxes[i][2]==boxes[j][2]))
853  {
854  if(boxes[i][1]==boxes[j][3])
855  {
856  boxes[i][1] = boxes[j][1];
857  boxes.erase(boxes.begin()+j);
858  s--;
859  j--;
860  change = true;
861  }
862  if(boxes[i][3]==boxes[j][1])
863  {
864  boxes[i][3] = boxes[j][3];
865  boxes.erase(boxes.begin()+j);
866  s--;
867  j--;
868  change = true;
869  }
870  }
871  if( (boxes[i][1]==boxes[j][1]) && (boxes[i][3]==boxes[j][3])
872 )
873  {
874  if(boxes[i][0]==boxes[j][2])
875  {
876  boxes[i][0] = boxes[j][0];
877  boxes.erase(boxes.begin()+j);
878  s--;
879  j--;
880  change = true;
881  }
882  if(boxes[i][2]==boxes[j][0])
883  {
884  boxes[i][2] = boxes[j][2];
885  boxes.erase(boxes.begin()+j);
886  s--;
887  j--;
888  change = true;
889  }
890  }
891  }
892  }
893  }
894  }
895 }
896 
897 template<short_t d, class Z> void
898 gsHDomain<d, Z>::connect_Boxes(std::vector<std::vector<Z>> &boxes) const
899 {
900  bool change = true;
901  while(change)
902  {
903  change = false;
904  size_t s = boxes.size();
905  for(size_t i = 0; i < s; i++)
906  {
907  for(size_t j = i+1; j < s; j++)
908  {
909  if(boxes[i][2*d]==boxes[j][2*d]) // if( the levels are the same )
910  {
911  unsigned nmCoordLo = 0;
912  unsigned nmCoordUp = 0;
913  unsigned nmCountUp = 0;
914  unsigned nmCountLo = 0; //...the "nm" is for non-matching
915 
916  // Compare the lower and upper corners of the boxes
917  // coordinate-wise, and check if there are differences.
918  // If there are differences, count and store the coordinate
919  for(short_t k=0; k < d; k++)
920  {
921  if( boxes[i][k] != boxes[j][k] )
922  {
923  nmCountLo++;
924  nmCoordLo = k;
925  }
926 
927  if( boxes[i][d+k] != boxes[j][d+k] )
928  {
929  nmCountUp++;
930  nmCoordUp = k;
931  }
932  }
933 
934  // The boxes can only be merged if
935  // the lower and upper corners are the same,
936  // except in one coordinate direction.
937  if( nmCountLo == 1
938  && nmCountUp == 1
939  && nmCoordLo == nmCoordUp )
940  {
941 
942  if( boxes[i][nmCoordLo] == boxes[j][d+nmCoordUp] )
943  {
944  // box i is "on top" of box j.
945  // It inherits the lower corner from box j:
946  boxes[i][nmCoordLo] = boxes[j][nmCoordLo];
947  boxes.erase( boxes.begin()+j );
948  s--;
949  j--;
950  change = true;
951  }
952 
953  if( boxes[i][d+nmCoordUp] == boxes[i][nmCoordLo] )
954  {
955  // box i is "below" of box j.
956  // It inherits the upper corner from box j:
957  boxes[i][d+nmCoordUp] = boxes[j][d+nmCoordUp];
958  boxes.erase( boxes.begin()+j );
959  s--;
960  j--;
961  change = true;
962  }
963  }
964  } // if boxes same level
965  } // for j
966  } // for i
967  }
968 }
969 
970 
971 template<short_t d, class Z>
972 void gsHDomain<d, Z>::connect_Boxes_2(std::vector<std::vector<Z> > &boxes) const
973 {
974  bool change = true;
975  while(change)
976  {
977  change = false;
978  size_t s = boxes.size();
979  for(size_t i = 0; i < s;i++)
980  {
981  for(size_t j = i+1; j < s; j++)
982  {
983  if(boxes[i][4]==boxes[j][4])
984  {
985  if( (boxes[i][0]==boxes[j][0]) && (boxes[i][2]==boxes[j][2]))
986  {
987  if(boxes[i][1]==boxes[j][3])
988  {
989  boxes[i][1] = boxes[j][1];
990  boxes.erase(boxes.begin()+j);
991  s--;
992  j--;
993  change = true;
994  }
995  if(boxes[i][3]==boxes[j][1])
996  {
997  boxes[i][3] = boxes[j][3];
998  boxes.erase(boxes.begin()+j);
999  s--;
1000  j--;
1001  change = true;
1002  }
1003  }
1004  }
1005  }
1006  }
1007  }
1008  change = true;
1009  while(change)
1010  {
1011  change = false;
1012  size_t s = boxes.size();
1013  for(size_t i = 0; i < s;i++)
1014  {
1015  for(size_t j = i+1; j < s; j++)
1016  {
1017  if( (boxes[i][1]==boxes[j][1]) && (boxes[i][3]==boxes[j][3]))
1018  {
1019  if(boxes[i][0]==boxes[j][2])
1020  {
1021  boxes[i][0] = boxes[j][0];
1022  boxes.erase(boxes.begin()+j);
1023  s--;
1024  j--;
1025  change = true;
1026  }
1027  if(boxes[i][2]==boxes[j][0])
1028  {
1029  boxes[i][2] = boxes[j][2];
1030  boxes.erase(boxes.begin()+j);
1031  s--;
1032  j--;
1033  change = true;
1034  }
1035  }
1036  }
1037  }
1038  }
1039 }
1040 
1041 
1042 
1043 template<short_t d, class Z> void
1044 gsHDomain<d, Z>::getBoxes_vec(std::vector<std::vector<Z> >& boxes) const
1045 {
1046  boxes.clear();
1047 
1048  std::stack<node*, std::vector<node*> > stack;
1049  //stack.reserve( 2 * m_maxPath );
1050  stack.push(m_root);
1051  node * curNode;
1052  while ( ! stack.empty() )
1053  {
1054  curNode = stack.top();
1055  stack.pop();
1056 
1057  if ( curNode->isLeaf() )
1058  {
1059  // We need to convert the indices to those of m_maxInsLevel
1060  // to be able to reconstruct the earlier results.
1061  const point & lowerGlob = curNode->lowCorner();
1062  const point & upperGlob = curNode->uppCorner();
1063  unsigned int level = this->m_maxInsLevel;
1064  point lower;
1065  point upper;
1066 
1067  global2localIndex(lowerGlob,level,lower);
1068  global2localIndex(upperGlob,level,upper);
1069 
1070  boxes.push_back(std::vector<Z>());
1071  for(short_t i = 0; i < d; i++)
1072  {
1073  boxes.back().push_back(lower[i]);
1074  }
1075  for(short_t i = 0; i < d; i++)
1076  {
1077  boxes.back().push_back(upper[i]);
1078  }
1079  boxes.back().push_back(curNode->level);
1080  }
1081  else
1082  {
1083  stack.push(curNode->left) ;
1084  stack.push(curNode->right);
1085  }
1086  }
1087 }
1088 
1089 /*
1090  * functions for returning the boudaries of domains
1091  */
1092 template<short_t d, class Z>
1093 std::vector<std::vector<std::vector< std::vector<Z> > > >
1095 {
1096 /*
1097  1: Get boxes from the quadtree.
1098  2: Return their borderlines.
1099 
1100  Return structure:
1101  < levels < polylines_in_one_level < one_polyline < one_segment (x1, y1, x2, y2) > > > > result
1102  note that <x1, y1, x2, y2 > are so that (x1, y1) <=LEX (x2, y2)
1103 */
1104  std::vector<std::vector<Z> > boxes;
1105  getBoxes_vec(boxes);// Returns all leaves.
1106 
1107  // Get rid of boxes that are not of full dimension.
1108  for(auto it = boxes.begin(); it != boxes.end(); ++it)
1109  {
1110  if( ( (*it)[0] == (*it)[2] ) || ( (*it)[0] == (*it)[2] ) )
1111  it = boxes.erase(it);
1112  }
1113 
1114  std::vector<std::vector<gsVSegment<Z> > > seg;
1115  seg.resize(m_maxInsLevel+1);
1116 
1117  // For each level prepare the vertical lines separately.
1118  for(size_t i = 0; i < boxes.size() ; i ++)
1119  {
1120  seg[boxes[i][4]].push_back(gsVSegment<Z>(boxes[i][0], boxes[i][1], boxes[i][3], false));
1121  seg[boxes[i][4]].push_back(gsVSegment<Z>(boxes[i][2], boxes[i][1], boxes[i][3], false));
1122  }
1123 
1124  // Process vertical lines from each level separately.
1125  std::vector< std::vector<std::vector< std::vector<Z> > > > result;
1126  for(unsigned int i = 0; i < m_maxInsLevel+1; i++)
1127  {
1128  result.push_back( getPolylinesSingleLevel( seg[i] ));
1129  }
1130 
1131  return result;
1132 }
1133 
1134 
1135 template<short_t d, class Z>
1136 std::vector<std::vector< std::vector<Z> > > gsHDomain<d, Z>::getPolylinesSingleLevel(std::vector<gsVSegment<Z> >& seg) const
1137 {
1138  // For didactic purposes the interior of the function has been refined into two procedures
1139  // (overal length of the older version was intimidating and people would not like to read it then =)).
1140 
1141  // For each x coordinate there will be a list of vertical segments with this x coord.
1142  std::list< std::list< gsVSegment<Z> > > vert_seg_lists;
1143 
1144  // For returning
1145  std::vector< std::vector< std::vector<Z> > > result;
1146 
1147  // This magically sorts seg according to x value
1148  std::sort( seg.begin(), seg.end() );
1149 
1150  // Put stuff from seg into vert_seg_lists
1151  std::list< gsVSegment<Z> > segs_x; // segments with the same particular x coord
1152  for(auto it_seg = seg.begin(); it_seg != seg.end(); ++it_seg )
1153  {
1154  if( segs_x.empty() || (*it_seg).getX() == segs_x.front().getX() )
1155  segs_x.push_back( *it_seg );
1156  else
1157  {
1158  vert_seg_lists.push_back( segs_x );
1159  segs_x.erase( segs_x.begin(), segs_x.end() );
1160  segs_x.push_back( *it_seg );
1161  }
1162  // Possible simplification: if( !empty && != ){ verts_seg.push_back; erase }segs_x.push_back;
1163  }
1164  vert_seg_lists.push_back( segs_x );
1165  // So vert_seg_lists is now the list as specified before and segs_x we do not need any further.
1166 
1167  // Get rid of overlaps of the segments.
1168  getRidOfOverlaps( vert_seg_lists );
1169 
1170  // And now the key point: sweepline driven connect and merge procedure
1171  sweeplineConnectAndMerge( result, vert_seg_lists );
1172  return result;
1173 }
1174 
1175 template <short_t d, class Z>
1176 void gsHDomain<d, Z>::getRidOfOverlaps( std::list<std::list<gsVSegment<Z> > >& vert_seg_lists ) const
1177 {
1178  bool need_to_erase = false;
1179  for(auto it_x = vert_seg_lists.begin(); it_x != vert_seg_lists.end(); )
1180  {
1181  // For each x coordinate substract overlapping segments.
1182  for(auto it_slow = (*it_x).begin(); it_slow != (*it_x).end(); ++it_slow)
1183  {
1184  // Don't we need to start the next already at (*it_x).begin() ?
1185  for(auto it_quick = it_slow; it_quick != (*it_x).end(); ++it_quick)
1186  {
1187  if( it_quick != it_slow )
1188  {
1189  need_to_erase = it_slow->cannotDeleteOverlap( *it_quick) || need_to_erase;
1190  // We do not actually use need_to_erase as initially intended
1191  // but this prevents warnings (cannot_delete_overlap returns bool).
1192  }
1193  }
1194  }
1195 
1196  // Get rid of segments of zero length
1197  for(auto it_slow = (*it_x).begin(); it_slow != (*it_x).end(); )
1198  {
1199  if( (*it_slow).length() == 0 )
1200  {
1201  (*it_x).erase( it_slow++ );
1202  }
1203  else
1204  ++it_slow; // Here instead of the internal for.
1205  }
1206 
1207  // There might be some empty lists;
1208  if( (*it_x).empty() )
1209  vert_seg_lists.erase( it_x++ );
1210  else
1211  ++it_x; // Here instead of the outer for.
1212  }
1213 }
1214 
1215 template <short_t d, class Z>
1216 void gsHDomain<d, Z>::sweeplineConnectAndMerge( std::vector< std::vector< std::vector<Z> > >& result,
1217  std::list< std::list< gsVSegment<Z> > >& vert_seg_lists ) const
1218 {
1219  /*========================
1220  * Algorithm description:
1221  *========================
1222  * The segments in vert_seg_lists are vertical sides of the boxes from the quadtree after getting rid of overlapping ones.
1223  * The sweepline proceeds from left to right.
1224  * Events: new x-coordinate
1225  * State: list of active (or open) polylines (their part to the left from the sweepline is non-empty and does not form an open polyline yet).
1226  * In each event we:
1227  * 1] Try to append vertical segments to the active lines. Report those that get closed.
1228  * 2] Remaining segments become polylines.
1229  * 3] Try to merge active polylines. Report those that get closed.
1230  * Remark: in kissing vertices (point, where two vertical and two horizontal line segments meet) we are allowed to turn left or right
1231  * BUT we are not allowed to go straight there. In other words, the interior must remain on the same hand side (left or right) the whole time.
1232  */
1233 
1234  // vector of active polylines
1235  std::list< gsAAPolyline<Z> > act_poly;
1236  std::queue< gsAAPolyline<Z> > poly_queue;
1237 
1238  for(auto it_x = vert_seg_lists.begin(); it_x != vert_seg_lists.end(); ++it_x )
1239  {
1240  // Try to extend polylines by adding segments to them.
1241  // The funny queue procedure is a trick to make sure that none of the polylines
1242  // would be extended too much (i.e., over a vertex, where it should be closed).
1243  for(auto it = act_poly.begin(); it != act_poly.end(); ++it )
1244  poly_queue.push( *it );
1245 
1246  act_poly.erase( act_poly.begin(), act_poly.end() );
1247 
1248  gsAAPolyline<Z> curr_poly;
1249  while( !poly_queue.empty() )
1250  {
1251  curr_poly = poly_queue.front();
1252  poly_queue.pop();
1253  bool is_active = true;
1254  for(auto it_seg = (*it_x).begin(); it_seg != (*it_x).end(); )
1255  {
1256  if( curr_poly.canBeExtended( *it_seg) )
1257  {
1258  if( curr_poly.almostClosed() )
1259  result.push_back( curr_poly.writeParasolid () );
1260  else
1261  poly_queue.push( curr_poly ); // This is the prevention of wrong behaviour in kissing vertices (cf. Remark above).
1262 
1263 
1264  (*it_x).erase( it_seg++ );
1265  is_active = false;
1266  break;
1267  }
1268  else
1269  ++it_seg;
1270  }
1271  if( is_active )
1272  {
1273  act_poly.push_back( curr_poly );
1274  }
1275  }
1276 
1277  // The remaining segments become polylines.
1278  for(auto it = (*it_x).begin(); it != (*it_x).end(); ++it )
1279  {
1280  gsAAPolyline<Z> new_polyline( *it );
1281  act_poly.push_back( new_polyline );
1282  }
1283 
1284  // Merge what's possible.
1285  // Trick: go through act_poly from left to right. Check each of them with all to the right of it in act_poly.
1286  // If they can be merged, move it to the end. Those more to the left are already finalised.
1287  // Could be replaced by sorting them first according to y-coordinate (David's suggestion) and then connecting
1288  // but I ran into some implementation trouble.
1289  for(auto it_slow = act_poly.begin(); it_slow != act_poly.end(); ++it_slow )
1290  {
1291  for(auto it_quick = it_slow; it_quick != act_poly.end(); ++it_quick)
1292  {
1293  if(( it_slow != it_quick ) && ((*it_slow).mergeWith(*it_quick)))
1294  {
1295  act_poly.erase( it_quick );
1296  act_poly.push_back( *it_slow );
1297  it_slow = act_poly.erase( it_slow );
1298  it_quick = it_slow;
1299  }
1300  }
1301  }
1302 
1303  // Check for closed lines as a result of the merging.
1304  for(auto it = act_poly.begin(); it != act_poly.end(); )
1305  {
1306  if( (*it).almostClosed() )
1307  {
1308  result.push_back( (*it).writeParasolid() );
1309  act_poly.erase( it++ );
1310  }
1311  else
1312  ++it;
1313 
1314  }
1315  }
1316 }
1317 
1318 template<short_t d, class Z>
1319 inline void gsHDomain<d, Z>::computeFinestIndex(gsVector<Z, d> const & index,
1320  unsigned lvl,
1321  gsVector<Z, d> & result) const
1322 {
1323  for(short_t i = 0; i!=d; ++i)
1324  result[i] = index[i] << (m_maxInsLevel-lvl) ;
1325 }
1326 
1327 template<short_t d, class Z>
1328 inline void gsHDomain<d, Z>::computeLevelIndex(gsVector<Z, d> const & index,
1329  unsigned lvl,
1330  gsVector<Z, d> & result) const
1331 {
1332  for(short_t i = 0; i!=d; ++i)
1333  result[i] = index[i] >> (m_maxInsLevel-lvl) ;
1334 }
1335 
1336 template<short_t d, class Z>
1337 inline void gsHDomain<d, Z>::local2globalIndex(gsVector<Z, d> const & index,
1338  unsigned lvl,
1339  gsVector<Z, d> & result) const
1340 {
1341  for(short_t i = 0; i!=d; ++i)
1342  result[i] = index[i] << (m_indexLevel-lvl) ;
1343 }
1344 
1345 template<short_t d, class Z>
1346 inline void gsHDomain<d, Z>::global2localIndex(gsVector<Z, d> const & index,
1347  unsigned lvl,
1348  gsVector<Z, d> & result) const
1349 {
1350  for(short_t i = 0; i!=d; ++i)
1351  result[i] = index[i] >> (this->m_indexLevel-lvl) ;
1352 }
1353 
1354 template<short_t d, class Z>
1356 {
1357  m_maxInsLevel++;
1358 
1359  GISMO_ASSERT( m_maxInsLevel <= m_indexLevel,
1360  "Problem with indices, increase number of levels (to do).");
1361 
1362  leafSearch< levelUp_visitor >();
1363 }
1364 
1365 template<short_t d, class Z>
1367 {
1368  m_upperIndex *= 2;
1369  nodeSearch< liftCoordsOneLevel_visitor >();
1370 }
1371 
1372 template<short_t d, class Z>
1374 {
1375  m_upperIndex /= 2;
1376  nodeSearch< reduceCoordsOneLevel_visitor >();
1377 }
1378 
1379 template<short_t d, class Z>
1381 {
1382  m_maxInsLevel--;
1383  leafSearch< levelDown_visitor >();
1384 }
1385 
1386 template<short_t d, class Z>
1387 inline int gsHDomain<d, Z>::size() const
1388 {
1389  return nodeSearch< numNodes_visitor >();
1390 }
1391 
1392 template<short_t d, class Z>
1393 inline int gsHDomain<d, Z>::leafSize() const
1394 {
1395  return leafSearch< numLeaves_visitor >();
1396 }
1397 
1398 template<short_t d, class Z>
1399 inline void gsHDomain<d, Z>::printLeaves() const
1400 {
1401  leafSearch< printLeaves_visitor >();
1402 }
1403 
1404 template<short_t d, class Z>
1406 {
1407  m_maxInsLevel = leafSearch< maxLevel_visitor >();
1408 }
1409 
1410 }// end namespace gismo
void decrementLevel()
Decrement the level index globally.
Definition: gsHDomain.hpp:1380
static bool isDegenerate(box const &someBox)
Returns true if the box is degenerate (has zero volume)
Definition: gsHDomain.hpp:136
gsHDomain * clone() const
Clones the object.
Definition: gsHDomain.hpp:96
static std::pair< point, point > select_part(point const &k1, point const &k2, point const &k3, point const &k4)
Definition: gsHDomain.hpp:488
Class for representing a vertical line segment in 2D. Helper for the class gsAAPolyline.
Definition: gsHDomain.h:33
bool query2(point const &lower, point const &upper, int level, node *_node) const
Returns true if the box defined by lower and upper is contained in a domain with a higher level than ...
Definition: gsHDomain.hpp:434
static bool haveOverlap(box const &box1, box const &box2)
Definition: gsHDomain.hpp:103
visitor::return_type nodeSearch() const
Definition: gsHDomain.hpp:610
int leafSize() const
Returns the number of leaves in the tree.
Definition: gsHDomain.hpp:1393
bool query1(point const &lower, point const &upper, int level, node *_node) const
Returns true if the box defined by lower and upper is completely contained in level and does not over...
Definition: gsHDomain.hpp:420
Helper class for gsAAPolyline.
#define short_t
Definition: gsConfig.h:35
Provides structs and classes related to interfaces and boundaries.
static bool isContained(box const &box1, box const &box2)
Returns true if box1 is contained in box2.
Definition: gsHDomain.hpp:110
gsKdNode * adaptiveAlignedSplit(kdBox const &insBox, int index_level)
Definition: gsKdNode.h:285
side
Identifiers for topological sides.
Definition: gsBoundary.h:58
void multiplyByTwo()
Multiply all coordinates by two.
Definition: gsHDomain.hpp:1366
gsKdNode * left
Pointer to the left child of this split node (if it is one)
Definition: gsKdNode.h:60
Struct representing a kd-tree node.
Definition: gsKdNode.h:34
#define index_t
Definition: gsConfig.h:32
void incrementLevel()
Increment the level index globally.
Definition: gsHDomain.hpp:1355
void getBoxesInLevelIndex(gsMatrix< Z > &b1, gsMatrix< Z > &b2, gsVector< index_t > &level) const
Definition: gsHDomain.hpp:790
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
std::vector< std::vector< std::vector< std::vector< Z > > > > getPolylines() const
Definition: gsHDomain.hpp:1094
void sweeplineConnectAndMerge(std::vector< std::vector< std::vector< Z > > > &result, std::list< std::list< gsVSegment< Z > > > &vert_seg_lists) const
Sweepline algorithm.
Definition: gsHDomain.hpp:1216
A matrix with arbitrary coefficient type and fixed or dynamic size.
Definition: gsMatrix.h:38
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
void clearBox(point const &lower, point const &upper, int lvl)
The clear function which clears box defined by points lower and upper to level lvl.
Definition: gsHDomain.hpp:225
#define gsWarn
Definition: gsDebug.h:50
int query3(point const &k1, point const &k2, int level, node *_node) const
Definition: gsHDomain.hpp:448
Z pos
Split coordinate (meaningfull only for split nodes)
Definition: gsKdNode.h:45
void getBoxes(gsMatrix< Z > &b1, gsMatrix< Z > &b2, gsVector< Z > &level) const
Returns the boxes which make up the hierarchical domain and the respective levels.
Definition: gsHDomain.hpp:710
void printLeaves() const
Prints out the leaves of the kd-tree.
Definition: gsHDomain.hpp:1399
void sinkBox(point const &lower, point const &upper, int lvl)
Sinks the box defined by points lower and upper to one level higher.
Definition: gsHDomain.hpp:304
std::pair< int, int > minMaxPath() const
Returns the minimim and maximum path length in the tree.
Definition: gsHDomain.hpp:675
node * pointSearch(const point &p, int level, node *_node) const
Definition: gsHDomain.hpp:572
void getRidOfOverlaps(std::list< std::list< gsVSegment< Z > > > &vert_seg_lists) const
Definition: gsHDomain.hpp:1176
int size() const
Returns the number of nodes in the tree.
Definition: gsHDomain.hpp:1387
Class with a hierarchical domain structure represented by a box k-d-tree.
Definition: gsHDomain.h:75
static void setLevel(node *_node, int lvl)
Definition: gsHDomain.hpp:117
int level
Definition: gsKdNode.h:49
void getBoxes_vec(std::vector< std::vector< Z >> &boxes) const
Represents boxes of the tree in a big vector.
Definition: gsHDomain.hpp:1044
void insertBox(point const &lower, point const &upper, node *_node, int lvl)
The insert function which insert box defined by points lower and upper to level lvl.
Definition: gsHDomain.hpp:143
Class for handling an axis-aligned polyline in 2D.
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
Struct of for an Axis-aligned bounding box.
Definition: gsAABB.h:30
This is the main header file that collects wrappers of Eigen for linear algebra.
kdBox * box
Definition: gsKdNode.h:54
visitor::return_type leafSearch() const
Definition: gsHDomain.hpp:642
gsKdNode * parent
Pointer to the parent node.
Definition: gsKdNode.h:57
visitor::return_type boxSearch(point const &k1, point const &k2, int level, node *_node) const
Definition: gsHDomain.hpp:518
int axis
Definition: gsKdNode.h:42
void divideByTwo()
Divide all coordinates by two.
Definition: gsHDomain.hpp:1373
Provides declaration of the tree node.
void getBoxesOnSide(boundary::side s, gsMatrix< Z > &b1, gsMatrix< Z > &b2, gsVector< Z > &level) const
Returns the boxes which make up the hierarchical domain and the respective levels touching side s...
Definition: gsHDomain.hpp:739
void connect_Boxes(std::vector< std::vector< Z > > &boxes) const
connect the boxes returned from quadtree getBoxes_vec()
Definition: gsHDomain.hpp:898
int query4(point const &lower, point const &upper, int level, node *_node) const
Definition: gsHDomain.hpp:462
gsKdNode * right
Pointer to the right child of this split node (if it is one)
Definition: gsKdNode.h:63