49 m_maxDepth(0), m_root(nullptr)
73 m_root = std::make_shared<Octant>(0, 1, 0, bounds);
74 m_root->SetIndices(indices);
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];
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];
119 for (
int i = 0; i < 6; ++i)
121 bounds[i] -= pow(-1,i) * margin;
125 Octree(pts, maxPts, bounds);
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]))
154 while (!node->IsLeaf() && node->GetDepth() < depth)
156 int loc = node->GetLocInNode(coords);
157 node = node->GetChildren()[
loc-1];
160 nodeID = node->GetID();
182 distance = std::numeric_limits<NekDouble>::max();
198 std::vector<int> indices(
m_nodes[nodeInd]->GetIndices());
201 for (
int i : neigh.lock()->GetIndices())
203 indices.push_back(i);
208 for (
int i : indices)
212 for (
int j = 1; j < 3; ++j)
214 sub = pts[i][j]-coords[j];
215 tmpDistance += sub * sub;
219 if (distance > tmpDistance)
221 distance = tmpDistance;
238 return m_nodes[nodeID]->GetIndices();
253 std::vector<int> indices;
256 indices.push_back(node.lock()->GetID());
271 int &nLeaves,
int &depth)
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},
323 if (!
m_nodes[nodeID]->IsLeaf())
334 for (
int step = 0; step < 26; ++step)
336 for (
int i = 0; i < 3; ++i)
338 probeCoords[i] +=
m_nodes[nodeID]->GetDelta()*steps[step][i];
345 std::vector<OctantSharedPtr> leaves;
346 m_nodes[neighInd]->GetLeaves(leaves);
347 m_nodes[nodeID]->AddNeighbours(leaves);
358 m_delta(-1), m_centre(3), m_bounds(6), m_isLeaf(true)
372 m_nPts(0), m_loc(
loc), m_depth(depth),
373 m_id(id), m_isLeaf(true)
376 if (bounds.size() != 6)
378 throw std::out_of_range(
"Size of bounds must be 6.");
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)
387 m_delta = (deltaX > deltaY) ? deltaX : deltaY;
398 for (
int i = 0; i < 3; ++i)
400 m_centre[i] = (bounds[2*i+1] + bounds[2*i])/2.0;
413 m_id(-1), m_isLeaf(true)
468 throw std::out_of_range(
"Loc must be in the range (1,8).");
472 m_centre[0] = pCentre[0] + centreDX;
473 m_centre[1] = pCentre[1] + centreDY;
474 m_centre[2] = pCentre[2] + centreDZ;
478 for (
int i = 0; i < 3; ++i)
495 leaves.push_back(shared_from_this());
501 child->GetLeaves(leaves);
513 for (
int i : indices)
515 m_pointInd.push_back(i);
517 m_nPts = indices.size();
526 const std::vector<OctantSharedPtr> &neighbours)
533 if (neigh.lock()->GetID() == neighbour->GetID())
541 m_neighbours.push_back(neighbour);
554 const std::vector<int> &indices)
556 for (
int i : indices)
560 if ((pt[0] < m_bounds[0]) || (pt[0] > m_bounds[1]))
564 if ((pt[1] < m_bounds[2]) || (pt[1] > m_bounds[3]))
568 if ((pt[2] < m_bounds[4]) || (pt[2] > m_bounds[5]))
575 m_pointInd.push_back(i);
592 std::vector<OctantSharedPtr> &nodes)
599 for (
int i = 0; i < 8; ++i)
602 std::make_shared<Octant>(i+1, *shared_from_this());
603 newChild->AddPoints(pts, m_pointInd);
604 newChild->SetID(nodes.size());
607 m_children[i] = newChild;
608 nodes.push_back(newChild);
611 newChild->Subdivide(maxPts, pts, nodes);
637 unsigned char posByte;
639 if (coords[0] <= m_centre[0])
647 if (coords[1] <= m_centre[1])
655 if (coords[2] <= m_centre[2])
668 posByte = posByte >> 1;
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)
Array< OneD, NekDouble > & GetCentre()
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....
The above copyright notice and this permission notice shall be included.
scalarT< T > sqrt(scalarT< T > in)