Nektar++
Octree.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File Octree.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Implementation of an octree sorting algorithm.
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include "Octree.h"
36 #include <stdexcept>
37 #include <cmath>
38 
39 namespace Nektar
40 {
41 namespace FieldUtils
42 {
43 
44 /**
45  * @brief Construct a new octree object
46  *
47  */
48 Octree::Octree() : m_maxPts(0), m_nMshPts(0), m_nNodes(0), m_nLeaves(0),
49  m_maxDepth(0), m_root(nullptr)
50 {
51 }
52 
53 /**
54  * @brief Construct a new octree object
55  *
56  * @param pts
57  * @param maxPts
58  * @param bounds
59  */
60 Octree::Octree(const Array<OneD, Array<OneD, NekDouble> > &pts, int maxPts,
61  const Array<OneD, NekDouble> &bounds)
62 {
63  // Set some values
64  m_maxPts = maxPts;
65  m_nMshPts = pts.size();
66 
67  // Create first (root) node
68  std::vector<int> indices(m_nMshPts);
69  for (int i = 0; i < m_nMshPts; ++i)
70  {
71  indices[i] = i;
72  }
73  m_root = std::make_shared<Octant>(0, 1, 0, bounds);
74  m_root->SetIndices(indices);
75  m_nodes.push_back(m_root);
76 
77  // Create the tree
78  m_root->Subdivide(m_maxPts, pts, m_nodes);
79 
80  // Get some data after the tree is computed
81  m_maxDepth = 0;
82  AdvanceToStats(m_root->GetID());
83  m_nNodes = m_nodes.size();
84 
85  // Set the pointers to the neighbouring nodes
86  SetNeighbours(m_root->GetID());
87 }
88 
89 /**
90  * @brief Construct a new octree object
91  *
92  * @param pts
93  * @param maxPts
94  */
95 Octree::Octree(const Array<OneD, Array<OneD, NekDouble> > &pts, int maxPts)
96 {
97  // Small margin to avoid rounding errors
98  NekDouble margin = 1e-10;
99 
100  // Find coordinates of the bounding box
101  Array<OneD, NekDouble> bounds(6);
102  bounds[0] = pts[0][0];
103  bounds[1] = pts[0][0];
104  bounds[2] = pts[0][1];
105  bounds[3] = pts[0][1];
106  bounds[4] = pts[0][2];
107  bounds[5] = pts[0][2];
108  for (int i = 1; i < m_nMshPts; ++i)
109  {
110  bounds[0] = (bounds[0] < pts[i][0]) ? bounds[0] : pts[i][0];
111  bounds[1] = (bounds[1] > pts[i][0]) ? bounds[1] : pts[i][0];
112  bounds[2] = (bounds[2] < pts[i][1]) ? bounds[2] : pts[i][1];
113  bounds[3] = (bounds[3] > pts[i][1]) ? bounds[3] : pts[i][1];
114  bounds[4] = (bounds[4] < pts[i][2]) ? bounds[4] : pts[i][2];
115  bounds[5] = (bounds[5] > pts[i][2]) ? bounds[5] : pts[i][2];
116  }
117 
118  // Add the margin
119  for (int i = 0; i < 6; ++i)
120  {
121  bounds[i] -= pow(-1,i) * margin;
122  }
123 
124  // Call the octree constructor
125  Octree(pts, maxPts, bounds);
126 }
127 
128 /**
129  * @brief Given the coordinates 'coords' of a point, returns the leaf octant
130  * that contains it. If 'depth' is specified, returs the node that contains the
131  * point such that its depth is lower or equal to the one indicated. If the
132  * point lies outside the tree, it returns -1
133  *
134  * @param coords
135  * @param depth
136  * @return int
137  */
138 int Octree::QueryNode(const Array<OneD, NekDouble> &coords, int depth)
139 {
140  int nodeID = -1;
141 
142  if (coords.size())
143  {
144  // First, check if inside the octree
145  Array<OneD, NekDouble> bounds = m_root->GetBounds();
146  if ((coords[0] >= bounds[0]) && (coords[0] <= bounds[1]) &&
147  (coords[1] >= bounds[2]) && (coords[1] <= bounds[3]) &&
148  (coords[2] >= bounds[4]) && (coords[2] <= bounds[5]))
149  {
150  // Initialise 'node'
151  OctantSharedPtr node = m_root;
152 
153  // Keep advancing towards the end of the branch
154  while (!node->IsLeaf() && node->GetDepth() < depth)
155  {
156  int loc = node->GetLocInNode(coords);
157  node = node->GetChildren()[loc-1];
158  }
159 
160  nodeID = node->GetID();
161  }
162  }
163 
164  return nodeID;
165 }
166 
167 /**
168  * @brief Finds the ID of the closest point in 'pts' to the one specified by
169  * 'coords'. It also returns the distance between both points in 'distance'
170  *
171  * @param pts
172  * @param coords
173  * @param distance
174  * @param pointInd
175  * @return int
176  */
178  const Array<OneD, NekDouble> &coords,
179  NekDouble &distance, int pointInd)
180 {
181  int index = -1;
182  distance = std::numeric_limits<NekDouble>::max();
183 
184  if (coords.size())
185  {
186  // Find the corresponding node to 'coords'
187  int nodeInd;
188  if (pointInd > 0)
189  {
190  nodeInd = pointInd;
191  }
192  else
193  {
194  nodeInd = QueryNode(coords);
195  }
196 
197  // List the indices of all the candidate points
198  std::vector<int> indices(m_nodes[nodeInd]->GetIndices());
199  for (OctantWeakPtr neigh : m_nodes[nodeInd]->GetNeighbours())
200  {
201  for (int i : neigh.lock()->GetIndices())
202  {
203  indices.push_back(i);
204  }
205  }
206 
207  // Check the distances with all the nodes
208  for (int i : indices)
209  {
210  NekDouble sub = pts[i][0]-coords[0];
211  NekDouble tmpDistance = sub * sub;
212  for (int j = 1; j < 3; ++j)
213  {
214  sub = pts[i][j]-coords[j];
215  tmpDistance += sub * sub;
216  }
217  tmpDistance = std::sqrt(tmpDistance);
218 
219  if (distance > tmpDistance)
220  {
221  distance = tmpDistance;
222  index = i;
223  }
224  }
225  }
226 
227  return index;
228 }
229 
230 /**
231  * @brief Returns the indices of the points of the mesh contained in the tree
232  *
233  * @param nodeID
234  * @return std::vector<int>
235  */
236 std::vector<int> Octree::QueryPoints(int nodeID)
237 {
238  return m_nodes[nodeID]->GetIndices();
239 }
240 
241 /**
242  * @brief Returns the IDs of the octants that surround the queried node. First,
243  * it finds the neighbouring nodes with the same or lower depth and, if they
244  * are not leaf nodes, return all the leaf octants contained in them. This
245  * means that, for octants of depth 2, this function returns all the leaf nodes
246  * in the tree except those lying inside the queried octant
247  *
248  * @param nodeID
249  * @return std::vector<int>
250  */
251 std::vector<int> Octree::QueryNeighbours(int nodeID)
252 {
253  std::vector<int> indices;
254  for (const OctantWeakPtr &node : m_nodes[nodeID]->GetNeighbours())
255  {
256  indices.push_back(node.lock()->GetID());
257  }
258  return indices;
259 }
260 
261 /**
262  * @brief Returns some characteristic values of the tree.
263  *
264  * @param maxPts
265  * @param nPts
266  * @param nNodes
267  * @param nLeaves
268  * @param depth
269  */
270 void Octree::GetStats(int &maxPts, int &nPts, int &nNodes,
271  int &nLeaves, int &depth)
272 {
273  maxPts = m_maxPts;
274  nPts = m_nMshPts;
275  nNodes = m_nNodes;
276  nLeaves = m_nLeaves;
277  depth = m_maxDepth;
278 }
279 
280 /**
281  * @brief Goes through all the nodes of the octree counting the number of
282  * octants and the maximum depth reached
283  *
284  * @param nodeID
285  */
286 void Octree::AdvanceToStats(int nodeID)
287 {
288  // Update stats if we reached the end of the branch
289  if (m_nodes[nodeID]->IsLeaf())
290  {
291  m_nLeaves++;
292  m_maxDepth = (m_maxDepth > m_nodes[nodeID]->GetDepth()) ? m_maxDepth :
293  m_nodes[nodeID]->GetDepth();
294  }
295  // In any other case, dig into the tree
296  else
297  {
298  Array<OneD, OctantSharedPtr> children = m_nodes[nodeID]->GetChildren();
299  for (OctantSharedPtr child : children)
300  {
301  AdvanceToStats(child->GetID());
302  }
303  }
304 }
305 
306 /**
307  * @brief Once the nodes of the octree are created, sets their neighbours as
308  * explained in 'Octree::QueryNeighbours'
309  *
310  * @param nodeID
311  */
312 void Octree::SetNeighbours(int nodeID)
313 {
314  // Array with the different steps
315  static int steps[26][3] = {{-1,-1,-1}, {1,0,0}, {1,0,0}, {0,1,0}, {0,1,0},
316  {-1,0,0}, {-1,0,0}, {0,-1,0}, {1,0,0},
317  {-1,-1,1}, {1,0,0}, {1,0,0}, {0,1,0}, {0,1,0},
318  {-1,0,0}, {-1,0,0}, {0,-1,0}, {0,-1,1}, {1,0,0},
319  {1,0,0}, {0,1,0}, {0,1,0}, {-1,0,0}, {-1,0,0},
320  {0,-1,0}, {1,0,0}};
321 
322  // Advance to the leaves of the octree
323  if (!m_nodes[nodeID]->IsLeaf())
324  {
325  for (OctantSharedPtr child : m_nodes[nodeID]->GetChildren())
326  {
327  SetNeighbours(child->GetID());
328  }
329  }
330  else
331  {
332  // delta * steps
333  Array<OneD, NekDouble> probeCoords(m_nodes[nodeID]->GetCentre());
334  for (int step = 0; step < 26; ++step)
335  {
336  for (int i = 0; i < 3; ++i)
337  {
338  probeCoords[i] += m_nodes[nodeID]->GetDelta()*steps[step][i];
339  }
340 
341  // For each neighbour, find the leaves and add them
342  int neighInd = QueryNode(probeCoords, m_nodes[nodeID]->GetDepth());
343  if (neighInd > -1)
344  {
345  std::vector<OctantSharedPtr> leaves;
346  m_nodes[neighInd]->GetLeaves(leaves);
347  m_nodes[nodeID]->AddNeighbours(leaves);
348  }
349  }
350  }
351 }
352 
353 /**
354  * @brief Construct a new Octree::Octant object
355  *
356  */
357 Octree::Octant::Octant() : m_nPts(-1), m_loc(-1), m_depth(-1), m_id(-1),
358  m_delta(-1), m_centre(3), m_bounds(6), m_isLeaf(true)
359 {
360 }
361 
362 /**
363  * @brief Construct a new Octree::Octant object
364  *
365  * @param loc
366  * @param depth
367  * @param id
368  * @param bounds
369  */
370 Octree::Octant::Octant(int loc, int depth, int id,
371  const Array<OneD, NekDouble> &bounds) :
372  m_nPts(0), m_loc(loc), m_depth(depth),
373  m_id(id), m_isLeaf(true)
374 {
375  // Check the size of 'bounds'
376  if (bounds.size() != 6)
377  {
378  throw std::out_of_range("Size of bounds must be 6.");
379  }
380 
381  // If all deltas are not equal, use the largest ones
382  NekDouble deltaX = bounds[1] - bounds[0];
383  NekDouble deltaY = bounds[3] - bounds[2];
384  NekDouble deltaZ = bounds[5] - bounds[4];
385  if (deltaX != deltaY || deltaY != deltaZ)
386  {
387  m_delta = (deltaX > deltaY) ? deltaX : deltaY;
388  m_delta = (m_delta > deltaZ) ? m_delta : deltaZ;
389  }
390  else
391  {
392  m_delta = deltaX;
393  }
394 
395  // Fill in the rest of the data
398  for (int i = 0; i < 3; ++i)
399  {
400  m_centre[i] = (bounds[2*i+1] + bounds[2*i])/2.0;
401  m_bounds[2*i] = m_centre[i] - m_delta/2.0;
402  m_bounds[2*i+1] = m_centre[i] + m_delta/2.0;
403  }
404 }
405 
406 /**
407  * @brief Construct a new Octree::Octant object
408  *
409  * @param loc
410  * @param parent
411  */
412 Octree::Octant::Octant(int loc, Octant &parent) : m_nPts(0), m_loc(loc),
413  m_id(-1), m_isLeaf(true)
414 {
415  // Set depth
416  m_depth = parent.GetDepth() + 1;
417 
418  // Set delta
419  m_delta = parent.GetDelta()/2.0;
420 
421  // Set centre
422  NekDouble centreDX;
423  NekDouble centreDY;
424  NekDouble centreDZ;
425  switch (loc)
426  {
427  case 1: // x-, y-, z-
428  centreDX = -m_delta/2.0;
429  centreDY = -m_delta/2.0;
430  centreDZ = -m_delta/2.0;
431  break;
432  case 2: // x+, y-, z-
433  centreDX = m_delta/2.0;
434  centreDY = -m_delta/2.0;
435  centreDZ = -m_delta/2.0;
436  break;
437  case 3: // x+, y+, z-
438  centreDX = m_delta/2.0;
439  centreDY = m_delta/2.0;
440  centreDZ = -m_delta/2.0;
441  break;
442  case 4: // x-, y+, z-
443  centreDX = -m_delta/2.0;
444  centreDY = m_delta/2.0;
445  centreDZ = -m_delta/2.0;
446  break;
447  case 5: // x-, y-, z+
448  centreDX = -m_delta/2.0;
449  centreDY = -m_delta/2.0;
450  centreDZ = m_delta/2.0;
451  break;
452  case 6: // x+, y-, z+
453  centreDX = m_delta/2.0;
454  centreDY = -m_delta/2.0;
455  centreDZ = m_delta/2.0;
456  break;
457  case 7: // x+, y+, z+
458  centreDX = m_delta/2.0;
459  centreDY = m_delta/2.0;
460  centreDZ = m_delta/2.0;
461  break;
462  case 8: // x-, y+, z+
463  centreDX = -m_delta/2.0;
464  centreDY = m_delta/2.0;
465  centreDZ = m_delta/2.0;
466  break;
467  default:
468  throw std::out_of_range("Loc must be in the range (1,8).");
469  }
470  Array<OneD, NekDouble> pCentre = parent.GetCentre();
472  m_centre[0] = pCentre[0] + centreDX;
473  m_centre[1] = pCentre[1] + centreDY;
474  m_centre[2] = pCentre[2] + centreDZ;
475 
476  // Set bounds
478  for (int i = 0; i < 3; ++i)
479  {
480  m_bounds[2*i] = m_centre[i] - m_delta/2.0;
481  m_bounds[2*i+1] = m_centre[i] + m_delta/2.0;
482  }
483 }
484 
485 /**
486  * @brief Updates 'leaves' so that it contains all the leaf nodes belonging to
487  * the octant
488  *
489  * @param leaves
490  */
491 void Octree::Octant::GetLeaves(std::vector<OctantSharedPtr>& leaves)
492 {
493  if (m_isLeaf)
494  {
495  leaves.push_back(shared_from_this());
496  }
497  else
498  {
499  for (OctantSharedPtr child : m_children)
500  {
501  child->GetLeaves(leaves);
502  }
503  }
504 }
505 
506 /**
507  * @brief Sets the values of 'm_pointInd' to those in 'indices'
508  *
509  * @param indices
510  */
511 void Octree::Octant::SetIndices(const std::vector<int> &indices)
512 {
513  for (int i : indices)
514  {
515  m_pointInd.push_back(i);
516  }
517  m_nPts = indices.size();
518 }
519 
520 /**
521  * @brief Adds to 'm_neighbours' the octants that are not already in the list
522  *
523  * @param neighbours
524  */
526  const std::vector<OctantSharedPtr> &neighbours)
527 {
528  for (const OctantSharedPtr &neighbour : neighbours)
529  {
530  bool equal = false;
531  for (const OctantWeakPtr &neigh: m_neighbours)
532  {
533  if (neigh.lock()->GetID() == neighbour->GetID())
534  {
535  equal = true;
536  break;
537  }
538  }
539  if (!equal)
540  {
541  m_neighbours.push_back(neighbour);
542  }
543  }
544 }
545 
546 /**
547  * @brief Adds to 'm_pointInd' the IDs of the points in 'pts' that fall inside
548  * the octant
549  *
550  * @param pts
551  * @param indices
552  */
554  const std::vector<int> &indices)
555 {
556  for (int i : indices)
557  {
558  // Check if the point is inside the node
559  Array<OneD, NekDouble> pt = pts[i];
560  if ((pt[0] < m_bounds[0]) || (pt[0] > m_bounds[1]))
561  {
562  continue;
563  }
564  if ((pt[1] < m_bounds[2]) || (pt[1] > m_bounds[3]))
565  {
566  continue;
567  }
568  if ((pt[2] < m_bounds[4]) || (pt[2] > m_bounds[5]))
569  {
570  continue;
571  }
572 
573  // If so, add it to the list
574  m_nPts++;
575  m_pointInd.push_back(i);
576 
577  // Flag it as a leaf node
578  m_isLeaf = true;
579  }
580 }
581 
582 /**
583  * @brief Recursively divides the octant into 8 children and fills the leaf
584  * nodes with their corresponding points. Does NOT add neighbours
585  *
586  * @param maxPts
587  * @param pts
588  * @param nodes
589  */
591  const Array<OneD, Array<OneD, NekDouble> > &pts,
592  std::vector<OctantSharedPtr> &nodes)
593 {
594  // For a non-leaf node
595  if (m_nPts > maxPts)
596  {
597  // Create and fill children RECURSIVELY
598  m_children = Array<OneD, OctantSharedPtr>(8);
599  for (int i = 0; i < 8; ++i)
600  {
601  OctantSharedPtr newChild =
602  std::make_shared<Octant>(i+1, *shared_from_this());
603  newChild->AddPoints(pts, m_pointInd);
604  newChild->SetID(nodes.size()); // ID's start from 0
605 
606  // Add it to the list
607  m_children[i] = newChild;
608  nodes.push_back(newChild);
609 
610  // Keep dividing
611  newChild->Subdivide(maxPts, pts, nodes); // Recursion
612  }
613 
614  // Not a leaf node anymore
615  m_pointInd.clear();
616  m_nPts = 0;
617  m_isLeaf = false;
618  }
619 }
620 
621 /**
622  * @brief Returns the position inside an octant in the range (1-8). The name
623  * convention is as follows: let \f$\Delta\f$ be a value between 0 and the
624  * length of the side of the father octant, and \f$x_c,y_c,z_c\f$ be the
625  * coordinates of the centre of the father node. Then, position 1 corresponds
626  * to \f$x=x_c-\Delta\f$, \f$y=y_c-\Delta\f$ and \f$y=y_c-\Delta\f$. The next
627  * positions are obtained by rotating counter-clockwise around the Z axis and
628  * then, making the same rotation for \f$z=z_c+\Delta\f$
629  *
630  * @param coords
631  * @return int
632  */
634 {
635  // Different positions as bits in 'posByte'
636  // MSB <==> LSB
637  unsigned char posByte;
638 
639  if (coords[0] <= m_centre[0]) // x-
640  {
641  posByte = 153; //0b10011001;
642  }
643  else // x+
644  {
645  posByte = 102; //0b01100110;
646  }
647  if (coords[1] <= m_centre[1]) // y-
648  {
649  posByte &= 51; //0b00110011;
650  }
651  else // y+
652  {
653  posByte &= 204; //0b11001100;
654  }
655  if (coords[2] <= m_centre[2]) // z-
656  {
657  posByte &= 15; //0b00001111;
658  }
659  else // z+
660  {
661  posByte &= 240; //0b11110000;
662  }
663 
664  // Transform into a position in the range (1,8)
665  int position = 1;
666  while (posByte > 1)
667  {
668  posByte = posByte >> 1;
669  position++;
670  }
671 
672  return position;
673 }
674 }
675 }
Array< OneD, NekDouble > m_centre
Coordinates of the centre of the octant.
Definition: Octree.h:130
void AddPoints(const Array< OneD, Array< OneD, NekDouble > > &pts, const std::vector< int > &indices)
Adds to 'm_pointInd' the IDs of the points in 'pts' that fall inside the octant.
Definition: Octree.cpp:553
int m_depth
Depth in octree (root is 1)
Definition: Octree.h:124
double m_delta
Length of the octant side.
Definition: Octree.h:128
void AddNeighbours(const std::vector< OctantSharedPtr > &neighbours)
Adds to 'm_neighbours' the octants that are not already in the list.
Definition: Octree.cpp:525
void GetLeaves(std::vector< OctantSharedPtr > &leaves)
Updates 'leaves' so that it contains all the leaf nodes belonging to the octant.
Definition: Octree.cpp:491
void SetIndices(const std::vector< int > &indices)
Sets the values of 'm_pointInd' to those in 'indices'.
Definition: Octree.cpp:511
void Subdivide(int maxPts, const Array< OneD, Array< OneD, NekDouble > > &pts, std::vector< OctantSharedPtr > &nodes)
Recursively divides the octant into 8 children and fills the leaf nodes with their corresponding poin...
Definition: Octree.cpp:590
Array< OneD, NekDouble > m_bounds
Min/max coordinates of the octant (x, y, z)
Definition: Octree.h:132
Array< OneD, NekDouble > & GetCentre()
Definition: Octree.h:100
int GetLocInNode(const Array< OneD, NekDouble > &coords)
Returns the position inside an octant in the range (1-8). The name convention is as follows: let be ...
Definition: Octree.cpp:633
Octant()
Construct a new Octree::Octant object.
Definition: Octree.cpp:357
void SetNeighbours(int nodeID)
Once the nodes of the octree are created, sets their neighbours as explained in 'Octree::QueryNeighbo...
Definition: Octree.cpp:312
OctantSharedPtr m_root
First node of the tree, linked to the rest.
Definition: Octree.h:156
std::vector< int > QueryNeighbours(int nodeID)
Returns the IDs of the octants that surround the queried node. First, it finds the neighbouring nodes...
Definition: Octree.cpp:251
std::vector< int > QueryPoints(int nodeID)
Returns the indices of the points of the mesh contained in the tree.
Definition: Octree.cpp:236
int m_nNodes
Number of octants in the tree.
Definition: Octree.h:149
void GetStats(int &maxPts, int &nPts, int &nNodes, int &nLeaves, int &depth)
Returns some characteristic values of the tree.
Definition: Octree.cpp:270
int m_nLeaves
Number of leaf nodes in the tree.
Definition: Octree.h:151
std::shared_ptr< Octant > OctantSharedPtr
Definition: Octree.h:48
int QueryClosest(const Array< OneD, Array< OneD, NekDouble > > &pts, const Array< OneD, NekDouble > &coords, double &distance, int pointInd=-1)
Finds the ID of the closest point in 'pts' to the one specified by 'coords'. It also returns the dist...
Definition: Octree.cpp:177
std::weak_ptr< Octant > OctantWeakPtr
Definition: Octree.h:49
int m_maxPts
Max points allowed in each octant.
Definition: Octree.h:145
int m_maxDepth
Maximum depth of the tree.
Definition: Octree.h:153
void AdvanceToStats(int nodeID)
Goes through all the nodes of the octree counting the number of octants and the maximum depth reached...
Definition: Octree.cpp:286
Octree()
Construct a new octree object.
Definition: Octree.cpp:48
int m_nMshPts
Number of points in the mesh.
Definition: Octree.h:147
std::vector< OctantSharedPtr > m_nodes
Vector of pointers to every octant in the tree.
Definition: Octree.h:158
int QueryNode(const Array< OneD, NekDouble > &coords, int depth=std::numeric_limits< int >::max())
Given the coordinates 'coords' of a point, returns the leaf octant that contains it....
Definition: Octree.cpp:138
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
double NekDouble
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:267