47 : m_maxPts(0), m_nMshPts(0), m_nNodes(0), m_nLeaves(0), m_maxDepth(0),
72 m_root = std::make_shared<Octant>(0, 1, 0, bounds);
73 m_root->SetIndices(indices);
101 bounds[0] = pts[0][0];
102 bounds[1] = pts[0][0];
103 bounds[2] = pts[0][1];
104 bounds[3] = pts[0][1];
105 bounds[4] = pts[0][2];
106 bounds[5] = pts[0][2];
109 bounds[0] = (bounds[0] < pts[i][0]) ? bounds[0] : pts[i][0];
110 bounds[1] = (bounds[1] > pts[i][0]) ? bounds[1] : pts[i][0];
111 bounds[2] = (bounds[2] < pts[i][1]) ? bounds[2] : pts[i][1];
112 bounds[3] = (bounds[3] > pts[i][1]) ? bounds[3] : pts[i][1];
113 bounds[4] = (bounds[4] < pts[i][2]) ? bounds[4] : pts[i][2];
114 bounds[5] = (bounds[5] > pts[i][2]) ? bounds[5] : pts[i][2];
118 for (
int i = 0; i < 6; ++i)
120 bounds[i] -= pow(-1, i) * margin;
124 Octree(pts, maxPts, bounds);
145 if ((coords[0] >= bounds[0]) && (coords[0] <= bounds[1]) &&
146 (coords[1] >= bounds[2]) && (coords[1] <= bounds[3]) &&
147 (coords[2] >= bounds[4]) && (coords[2] <= bounds[5]))
153 while (!node->IsLeaf() && node->GetDepth() < depth)
155 int loc = node->GetLocInNode(coords);
156 node = node->GetChildren()[
loc - 1];
159 nodeID = node->GetID();
181 distance = std::numeric_limits<NekDouble>::max();
197 std::vector<int> indices(
m_nodes[nodeInd]->GetIndices());
200 for (
int i : neigh.lock()->GetIndices())
202 indices.push_back(i);
207 for (
int i : indices)
211 for (
int j = 1; j < 3; ++j)
213 sub = pts[i][j] - coords[j];
214 tmpDistance += sub * sub;
218 if (distance > tmpDistance)
220 distance = tmpDistance;
237 return m_nodes[nodeID]->GetIndices();
252 std::vector<int> indices;
255 indices.push_back(node.lock()->GetID());
315 static int steps[26][3] = {
316 {-1, -1, -1}, {1, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 1, 0},
317 {-1, 0, 0}, {-1, 0, 0}, {0, -1, 0}, {1, 0, 0}, {-1, -1, 1},
318 {1, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 1, 0}, {-1, 0, 0},
319 {-1, 0, 0}, {0, -1, 0}, {0, -1, 1}, {1, 0, 0}, {1, 0, 0},
320 {0, 1, 0}, {0, 1, 0}, {-1, 0, 0}, {-1, 0, 0}, {0, -1, 0},
324 if (!
m_nodes[nodeID]->IsLeaf())
335 for (
int step = 0; step < 26; ++step)
337 for (
int i = 0; i < 3; ++i)
339 probeCoords[i] +=
m_nodes[nodeID]->GetDelta() * steps[step][i];
346 std::vector<OctantSharedPtr> leaves;
347 m_nodes[neighInd]->GetLeaves(leaves);
348 m_nodes[nodeID]->AddNeighbours(leaves);
359 : m_nPts(-1), m_loc(-1), m_depth(-1), m_id(-1), m_delta(-1), m_centre(3),
360 m_bounds(6), m_isLeaf(true)
374 : m_nPts(0), m_loc(
loc), m_depth(depth), m_id(id), m_isLeaf(true)
377 if (bounds.size() != 6)
379 throw std::out_of_range(
"Size of bounds must be 6.");
383 NekDouble deltaX = bounds[1] - bounds[0];
384 NekDouble deltaY = bounds[3] - bounds[2];
385 NekDouble deltaZ = bounds[5] - bounds[4];
386 if (deltaX != deltaY || deltaY != deltaZ)
388 m_delta = (deltaX > deltaY) ? deltaX : deltaY;
399 for (
int i = 0; i < 3; ++i)
401 m_centre[i] = (bounds[2 * i + 1] + bounds[2 * i]) / 2.0;
414 : m_nPts(0), m_loc(
loc), m_id(-1), m_isLeaf(true)
469 throw std::out_of_range(
"Loc must be in the range (1,8).");
473 m_centre[0] = pCentre[0] + centreDX;
474 m_centre[1] = pCentre[1] + centreDY;
475 m_centre[2] = pCentre[2] + centreDZ;
479 for (
int i = 0; i < 3; ++i)
496 leaves.push_back(shared_from_this());
502 child->GetLeaves(leaves);
514 for (
int i : indices)
516 m_pointInd.push_back(i);
518 m_nPts = indices.size();
527 const std::vector<OctantSharedPtr> &neighbours)
534 if (neigh.lock()->GetID() == neighbour->GetID())
542 m_neighbours.push_back(neighbour);
555 const std::vector<int> &indices)
557 for (
int i : indices)
561 if ((pt[0] < m_bounds[0]) || (pt[0] > m_bounds[1]))
565 if ((pt[1] < m_bounds[2]) || (pt[1] > m_bounds[3]))
569 if ((pt[2] < m_bounds[4]) || (pt[2] > m_bounds[5]))
576 m_pointInd.push_back(i);
593 std::vector<OctantSharedPtr> &nodes)
600 for (
int i = 0; i < 8; ++i)
603 std::make_shared<Octant>(i + 1, *shared_from_this());
604 newChild->AddPoints(pts, m_pointInd);
605 newChild->SetID(nodes.size());
608 m_children[i] = newChild;
609 nodes.push_back(newChild);
612 newChild->Subdivide(maxPts, pts, nodes);
638 unsigned char posByte;
640 if (coords[0] <= m_centre[0])
648 if (coords[1] <= m_centre[1])
656 if (coords[2] <= m_centre[2])
669 posByte = posByte >> 1;
Array< OneD, NekDouble > & GetCentre()
Array< OneD, NekDouble > m_centre
Coordinates of the centre of the octant.
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.
int m_depth
Depth in octree (root is 1)
double m_delta
Length of the octant side.
void AddNeighbours(const std::vector< OctantSharedPtr > &neighbours)
Adds to 'm_neighbours' the octants that are not already in the list.
void GetLeaves(std::vector< OctantSharedPtr > &leaves)
Updates 'leaves' so that it contains all the leaf nodes belonging to the octant.
void SetIndices(const std::vector< int > &indices)
Sets the values of 'm_pointInd' to those in 'indices'.
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...
Array< OneD, NekDouble > m_bounds
Min/max coordinates of the octant (x, y, z)
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 ...
Octant()
Construct a new Octree::Octant object.
void SetNeighbours(int nodeID)
Once the nodes of the octree are created, sets their neighbours as explained in 'Octree::QueryNeighbo...
OctantSharedPtr m_root
First node of the tree, linked to the rest.
std::vector< int > QueryNeighbours(int nodeID)
Returns the IDs of the octants that surround the queried node. First, it finds the neighbouring nodes...
std::vector< int > QueryPoints(int nodeID)
Returns the indices of the points of the mesh contained in the tree.
int m_nNodes
Number of octants in the tree.
void GetStats(int &maxPts, int &nPts, int &nNodes, int &nLeaves, int &depth)
Returns some characteristic values of the tree.
int m_nLeaves
Number of leaf nodes in the tree.
std::shared_ptr< Octant > OctantSharedPtr
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...
std::weak_ptr< Octant > OctantWeakPtr
int m_maxPts
Max points allowed in each octant.
int m_maxDepth
Maximum depth of the tree.
void AdvanceToStats(int nodeID)
Goes through all the nodes of the octree counting the number of octants and the maximum depth reached...
Octree()
Construct a new octree object.
int m_nMshPts
Number of points in the mesh.
std::vector< OctantSharedPtr > m_nodes
Vector of pointers to every octant in the tree.
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....
scalarT< T > sqrt(scalarT< T > in)