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
39namespace Nektar
40{
41namespace 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 */
139int 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 */
237std::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 */
252std::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 */
271void 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 */
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 */
314void 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 */
374Octree::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 */
494void 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 */
514void 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 > & GetCentre()
Definition: Octree.h:130
Array< OneD, NekDouble > m_centre
Coordinates of the centre of the octant.
Definition: Octree.h:178
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
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 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
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
Array< OneD, NekDouble > m_bounds
Min/max coordinates of the octant (x, y, z)
Definition: Octree.h:180
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
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 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
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
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