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